This commit is contained in:
jfrijters 2005-02-02 15:11:26 +00:00
Родитель 62f7fb1d43
Коммит 744fef138d
48 изменённых файлов: 3941 добавлений и 3560 удалений

Просмотреть файл

@ -49,7 +49,7 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("0.10.0.1")] [assembly: AssemblyVersion("0.11.*")]
// //
// In order to sign your assembly you must specify a key to use. Refer to the // In order to sign your assembly you must specify a key to use. Refer to the

Просмотреть файл

@ -56,6 +56,7 @@ namespace ikvm.awt
public class NetToolkit : gnu.java.awt.ClasspathToolkit public class NetToolkit : gnu.java.awt.ClasspathToolkit
{ {
internal static System.Collections.ArrayList nativeQueue = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList());
private static java.awt.EventQueue eventQueue = new java.awt.EventQueue(); private static java.awt.EventQueue eventQueue = new java.awt.EventQueue();
private static volatile Form bogusForm; private static volatile Form bogusForm;
private static Delegate createControlInstance; private static Delegate createControlInstance;
@ -372,7 +373,7 @@ namespace ikvm.awt
return img; return img;
} }
public override java.awt.Image createImage(sbyte[] imagedata, int imageoffset, int imagelength) public override java.awt.Image createImage(byte[] imagedata, int imageoffset, int imagelength)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -440,6 +441,42 @@ namespace ikvm.awt
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override bool nativeQueueEmpty()
{
return nativeQueue.Count == 0;
}
public override void wakeNativeQueue()
{
// TODO if we're blocking in iterateNativeQueue() we should release that thread
}
public override void iterateNativeQueue(java.awt.EventQueue locked, bool block)
{
lock(nativeQueue)
{
if(nativeQueue.Count > 0)
{
locked.postEvent((java.awt.AWTEvent)nativeQueue[0]);
nativeQueue.RemoveAt(0);
return;
}
}
if(block)
{
Monitor.Exit(locked);
try
{
//Application.DoEvents();
Thread.Sleep(100);
}
finally
{
Monitor.Enter(locked);
}
}
}
} }
class NetFontPeer : gnu.java.awt.peer.ClasspathFontPeer class NetFontPeer : gnu.java.awt.peer.ClasspathFontPeer
@ -469,7 +506,7 @@ namespace ikvm.awt
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override sbyte getBaselineFor(java.awt.Font param1, char param2) public override byte getBaselineFor(java.awt.Font param1, char param2)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -660,7 +697,7 @@ namespace ikvm.awt
} }
public override void drawBytes(sbyte[] param1, int param2, int param3, int param4, int param5) public override void drawBytes(byte[] param1, int param2, int param3, int param4, int param5)
{ {
} }
@ -1346,7 +1383,8 @@ namespace ikvm.awt
protected void postEvent(java.awt.AWTEvent evt) protected void postEvent(java.awt.AWTEvent evt)
{ {
getToolkit().getSystemEventQueue().postEvent(evt); NetToolkit.nativeQueue.Add(evt);
//getToolkit().getSystemEventQueue().postEvent(evt);
} }
public int checkImage(java.awt.Image img, int width, int height, java.awt.image.ImageObserver ob) public int checkImage(java.awt.Image img, int width, int height, java.awt.image.ImageObserver ob)
@ -1743,7 +1781,7 @@ namespace ikvm.awt
Console.WriteLine("NetBufferedImage: setHints"); Console.WriteLine("NetBufferedImage: setHints");
} }
public void setPixels(int x, int y, int w, int h, ColorModel model, sbyte[] pixels, int off, int scansize) public void setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize)
{ {
Console.WriteLine("NetBufferedImage: setPixels1"); Console.WriteLine("NetBufferedImage: setPixels1");
} }

Двоичные данные
classpath/System.Xml.jar

Двоичный файл не отображается.

Двоичные данные
classpath/System.jar

Двоичный файл не отображается.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,8 +1,10 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<project name="IKVM.GNU.Classpath.dll" default="IKVM.GNU.Classpath.dll"> <project name="IKVM.GNU.Classpath.dll" default="IKVM.GNU.Classpath.dll">
<property name="Classpath.dir" value="${nant.project.basedir}/../../classpath-0.13" /> <property name="Classpath.dir" value="${nant.project.basedir}/../../classpath" />
<property name="pathsep" value=":" /> <property name="pathsep" value=":" />
<property overwrite="false" name="signoption" value="" /> <property overwrite="false" name="signoption" value="" />
<property name="jikes.compiler" value="true" />
<property name="ecj.compiler" value="false" />
<if propertytrue="nant.platform.win32"> <if propertytrue="nant.platform.win32">
<property name="pathsep" value=";" /> <property name="pathsep" value=";" />
@ -25,22 +27,27 @@
<includes name="**.class"/> <includes name="**.class"/>
</fileset> </fileset>
</delete> </delete>
<property name="classpath" value=".${pathsep}${Classpath.dir}${pathsep}${Classpath.dir}/external/w3c_dom${pathsep}${Classpath.dir}/external/sax${pathsep}${Classpath.dir}/vm/reference${pathsep}mscorlib.jar${pathsep}System.jar" /> <if propertytrue="jikes.compiler">
<exec program="jikes" commandline="-g -nowarn -classpath ${classpath} @allsources.lst"/> <property name="classpath" value=".${pathsep}${Classpath.dir}${pathsep}${Classpath.dir}/external/w3c_dom${pathsep}${Classpath.dir}/external/sax${pathsep}${Classpath.dir}/vm/reference${pathsep}mscorlib.jar${pathsep}System.jar" />
<exec program="jikes" commandline="-g -nowarn -classpath ${classpath} @allsources.lst"/>
</if>
<if propertytrue="ecj.compiler">
<exec program="ecj" commandline="-g -1.5 -nowarn -cp mscorlib.jar${pathsep}System.jar @allsources.lst"/>
</if>
</target> </target>
<target name="IKVM.GNU.Classpath.dll" depends="classes"> <target name="IKVM.GNU.Classpath.dll" depends="classes">
<exec program="${nant.project.basedir}/../bin/ikvmc.exe" useruntimeengine="true" commandline="-version:0.10.0.1 ${signoption} -monoBugWorkaround -opt:fields -nojni -out:IKVM.GNU.Classpath.dll -remap:map.xml -exclude:exclude.lst -target:library -recurse:./*.class -recurse:${Classpath.dir}/*.class -recurse:${Classpath.dir}/*.properties -recurse:${Classpath.dir}/resource/*.properties mscorlib.jar System.jar System.Xml.jar -resource:lib/security/classpath.security=classpath.security" /> <exec program="${nant.project.basedir}/../bin/ikvmc.exe" useruntimeengine="true" commandline="-version:0.11.* ${signoption} -monoBugWorkaround -opt:fields -nojni -out:IKVM.GNU.Classpath.dll -remap:map.xml -exclude:exclude.lst -target:library -recurse:./*.class -recurse:${Classpath.dir}/*.class -recurse:${Classpath.dir}/resource/*.properties mscorlib.jar System.jar System.Xml.jar -resource:lib/security/classpath.security=classpath.security" />
<copy file="IKVM.GNU.Classpath.dll" tofile="../bin/IKVM.GNU.Classpath.dll.new" /> <copy file="IKVM.GNU.Classpath.dll" tofile="../bin/IKVM.GNU.Classpath.dll.new" />
<if propertytrue="nant.platform.win32"> <if propertytrue="nant.platform.win32">
<call target="peverify-classpath"/> <call target="peverify-classpath"/>
</if> </if>
<copy file="IKVM.GNU.Classpath.dll" todir="../bin" /> <copy file="IKVM.GNU.Classpath.dll" todir="../bin" />
<delete file="../bin/IKVM.GNU.Classpath.dll.new" /> <delete file="../bin/IKVM.GNU.Classpath.dll.new" />
</target> </target>
<target name="peverify-classpath"> <target name="peverify-classpath">
<exec program="peverify" commandline="../bin/IKVM.GNU.Classpath.dll.new" /> <exec program="peverify" commandline="../bin/IKVM.GNU.Classpath.dll.new" />
</target> </target>
</project> </project>

Просмотреть файл

@ -45,7 +45,7 @@ public interface Configuration
{ {
// TODO // TODO
String CLASSPATH_HOME = ""; String CLASSPATH_HOME = "";
String CLASSPATH_VERSION = "0.13"; String CLASSPATH_VERSION = "0.13+cvs";
/** /**

Просмотреть файл

@ -0,0 +1,127 @@
/*
Copyright (C) 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
package gnu.classpath;
import cli.System.Diagnostics.StackFrame;
import cli.System.Diagnostics.StackTrace;
public final class VMStackWalker
{
private static final int SKIP_FRAMES = 2;
private static final cli.System.Reflection.Assembly mscorlib = cli.System.Type.GetType("System.Object").get_Assembly();
private static final cli.System.Type methodType = cli.System.Type.GetType("java.lang.reflect.Method");
private static final cli.System.Type constructorType = cli.System.Type.GetType("java.lang.reflect.Constructor");
private static final cli.System.Type jniEnvType = getJNIEnvType();
public static Class[] getClassContext()
{
StackTrace stack = new StackTrace(SKIP_FRAMES);
java.util.ArrayList list = new java.util.ArrayList();
for(int i = 0; i < stack.get_FrameCount(); i++)
{
StackFrame frame = stack.GetFrame(i);
// TODO handle reflection scenarios
cli.System.Type type = frame.GetMethod().get_DeclaringType();
if(type != null)
{
list.add(getClassFromType(type));
}
}
Class[] classes = new Class[list.size()];
list.toArray(classes);
return classes;
}
public static Class getCallingClass()
{
StackFrame frame = new StackFrame(SKIP_FRAMES);
cli.System.Type type = frame.GetMethod().get_DeclaringType();
if(isReflectionCaller(type))
{
type = getRealCaller(new StackTrace(SKIP_FRAMES + 1));
}
if(type != null)
{
return (Class)getClassFromType(type);
}
return null;
}
public static ClassLoader getCallingClassLoader()
{
StackFrame frame = new StackFrame(SKIP_FRAMES);
cli.System.Type type = frame.GetMethod().get_DeclaringType();
if(isReflectionCaller(type))
{
type = getRealCaller(new StackTrace(SKIP_FRAMES + 1));
}
if(type != null)
{
return (ClassLoader)getClassLoaderFromType(type);
}
return null;
}
private static boolean isReflectionCaller(cli.System.Type type)
{
if(type != null)
{
cli.System.Reflection.Assembly asm = type.get_Assembly();
// if we're being called by mscorlib, that means that reflection was used
return asm == mscorlib || asm == getNonVirtualInvokeAssembly();
}
return false;
}
private static cli.System.Type getRealCaller(StackTrace stack)
{
for(int i = 0; i < stack.get_FrameCount(); i++)
{
cli.System.Type type = stack.GetFrame(i).GetMethod().get_DeclaringType();
if(type == methodType || type == constructorType || type == jniEnvType)
{
while(++i < stack.get_FrameCount() && (type == methodType || type == constructorType || type == jniEnvType))
{
type = stack.GetFrame(i).GetMethod().get_DeclaringType();
}
if(type == null || i >= stack.get_FrameCount())
{
return null;
}
// If the reflection method was invoked by reflection, continue going up the stack.
if(isReflectionCaller(type))
{
continue;
}
return type;
}
}
return null;
}
private static native Object getClassFromType(cli.System.Type type);
private static native Object getClassLoaderFromType(cli.System.Type type);
private static native cli.System.Reflection.Assembly getNonVirtualInvokeAssembly();
private static native cli.System.Type getJNIEnvType();
}

Просмотреть файл

@ -49,7 +49,6 @@ import cli.System.Net.Sockets.SocketType;
import cli.System.Net.Sockets.ProtocolType; import cli.System.Net.Sockets.ProtocolType;
import cli.System.Net.Sockets.AddressFamily; import cli.System.Net.Sockets.AddressFamily;
import ikvm.lang.CIL; import ikvm.lang.CIL;
import ikvm.lang.ByteArrayHack;
/** /**
* This is the default socket implementation for datagram sockets. * This is the default socket implementation for datagram sockets.
@ -166,7 +165,7 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{ {
throw new SocketException("Invalid port"); throw new SocketException("Invalid port");
} }
if(socket.SendTo(ByteArrayHack.cast(packet.getData()), packet.getOffset(), len, SocketFlags.wrap(SocketFlags.None), new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(packet.getAddress()), port)) != len) if(socket.SendTo(packet.getData(), packet.getOffset(), len, SocketFlags.wrap(SocketFlags.None), new IPEndPoint(PlainSocketImpl.getAddressFromInetAddress(packet.getAddress()), port)) != len)
{ {
throw new SocketException("Not all data was sent"); throw new SocketException("Not all data was sent");
} }
@ -211,7 +210,7 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{ {
if(false) throw new cli.System.Net.Sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
if(false) throw new cli.System.ObjectDisposedException(""); if(false) throw new cli.System.ObjectDisposedException("");
int length = socket.ReceiveFrom(ByteArrayHack.cast(data), packet.getOffset(), getDatagramPacketBufferLength(packet), int length = socket.ReceiveFrom(data, packet.getOffset(), getDatagramPacketBufferLength(packet),
cli.System.Net.Sockets.SocketFlags.wrap(cli.System.Net.Sockets.SocketFlags.None), remoteEP); cli.System.Net.Sockets.SocketFlags.wrap(cli.System.Net.Sockets.SocketFlags.None), remoteEP);
setDatagramPacketLength(packet, length); setDatagramPacketLength(packet, length);
} }

Просмотреть файл

@ -51,7 +51,6 @@ import cli.System.Net.Sockets.ProtocolType;
import cli.System.Net.Sockets.AddressFamily; import cli.System.Net.Sockets.AddressFamily;
import cli.System.Net.Sockets.SocketShutdown; import cli.System.Net.Sockets.SocketShutdown;
import ikvm.lang.CIL; import ikvm.lang.CIL;
import ikvm.lang.ByteArrayHack;
/** /**
* Unless the application installs its own SocketImplFactory, this is the * Unless the application installs its own SocketImplFactory, this is the
@ -341,7 +340,7 @@ public class PlainSocketImpl extends SocketImpl
{ {
if(false) throw new cli.System.Net.Sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
if(false) throw new cli.System.ObjectDisposedException(""); if(false) throw new cli.System.ObjectDisposedException("");
return socket.Receive(ByteArrayHack.cast(buf), offset, len, SocketFlags.wrap(SocketFlags.None)); return socket.Receive(buf, offset, len, SocketFlags.wrap(SocketFlags.None));
} }
catch(cli.System.Net.Sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
@ -371,7 +370,7 @@ public class PlainSocketImpl extends SocketImpl
{ {
if(false) throw new cli.System.Net.Sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
if(false) throw new cli.System.ObjectDisposedException(""); if(false) throw new cli.System.ObjectDisposedException("");
socket.Send(ByteArrayHack.cast(buf), offset, len, SocketFlags.wrap(SocketFlags.None)); socket.Send(buf, offset, len, SocketFlags.wrap(SocketFlags.None));
} }
catch(cli.System.Net.Sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {
@ -667,7 +666,7 @@ public class PlainSocketImpl extends SocketImpl
if(false) throw new cli.System.Net.Sockets.SocketException(); if(false) throw new cli.System.Net.Sockets.SocketException();
if(false) throw new cli.System.ObjectDisposedException(""); if(false) throw new cli.System.ObjectDisposedException("");
byte[] oob = { (byte)data }; byte[] oob = { (byte)data };
socket.Send(ByteArrayHack.cast(oob), SocketFlags.wrap(SocketFlags.OutOfBand)); socket.Send(oob, SocketFlags.wrap(SocketFlags.OutOfBand));
} }
catch(cli.System.Net.Sockets.SocketException x) catch(cli.System.Net.Sockets.SocketException x)
{ {

Просмотреть файл

@ -81,20 +81,28 @@ class IkvmresURLConnection extends URLConnection
} }
try try
{ {
ResourceReader r = new ResourceReader(s); Object r;
try
{
r = ResourceReader.class.getConstructor(new Class[] { cli.System.IO.Stream.class }).newInstance(new Object[] { s });
}
catch(Exception x)
{
throw (IOException)new IOException().initCause(x);
}
try try
{ {
IEnumerator e = r.GetEnumerator(); IEnumerator e = ((IEnumerable)r).GetEnumerator();
if(!e.MoveNext()) if(!e.MoveNext())
{ {
throw new IOException("invalid resource " + resource + " found in assembly " + assembly); throw new IOException("invalid resource " + resource + " found in assembly " + assembly);
} }
inputStream = new ByteArrayInputStream(ikvm.lang.ByteArrayHack.cast((cli.System.Byte[])((DictionaryEntry)e.get_Current()).get_Value())); inputStream = new ByteArrayInputStream((byte[])((DictionaryEntry)e.get_Current()).get_Value());
connected = true; connected = true;
} }
finally finally
{ {
r.Close(); ((cli.System.IDisposable)r).Dispose();
} }
} }
finally finally

Просмотреть файл

@ -55,7 +55,6 @@ import java.nio.channels.WritableByteChannel;
import cli.System.Console; import cli.System.Console;
import cli.System.IO.*; import cli.System.IO.*;
import ikvm.lang.ByteArrayHack;
import ikvm.lang.CIL; import ikvm.lang.CIL;
/** /**
@ -382,7 +381,7 @@ public final class FileChannelImpl extends FileChannel
try try
{ {
if(false) throw new cli.System.IO.IOException(); if(false) throw new cli.System.IO.IOException();
int count = stream.Read(ByteArrayHack.cast(buf), offset, len); int count = stream.Read(buf, offset, len);
if(count == 0) if(count == 0)
{ {
count = -1; count = -1;
@ -416,6 +415,7 @@ public final class FileChannelImpl extends FileChannel
{ {
byte[] buffer = src.array(); byte[] buffer = src.array();
write(buffer, src.arrayOffset() + src.position(), len); write(buffer, src.arrayOffset() + src.position(), len);
src.position(src.position() + len);
} }
else else
{ {
@ -468,7 +468,7 @@ public final class FileChannelImpl extends FileChannel
{ {
if(false) throw new cli.System.IO.IOException(); if(false) throw new cli.System.IO.IOException();
if(false) throw new cli.System.ObjectDisposedException(null); if(false) throw new cli.System.ObjectDisposedException(null);
stream.Write(ByteArrayHack.cast(buf), offset, len); stream.Write(buf, offset, len);
// NOTE FileStream buffers the output, so we have to flush explicitly // NOTE FileStream buffers the output, so we have to flush explicitly
stream.Flush(); stream.Flush();
} }
@ -491,7 +491,7 @@ public final class FileChannelImpl extends FileChannel
{ {
if(false) throw new cli.System.IO.IOException(); if(false) throw new cli.System.IO.IOException();
if(false) throw new cli.System.ObjectDisposedException(null); if(false) throw new cli.System.ObjectDisposedException(null);
stream.WriteByte(CIL.box_ubyte((byte)b)); stream.WriteByte((byte)b);
// NOTE FileStream buffers the output, so we have to flush explicitly // NOTE FileStream buffers the output, so we have to flush explicitly
stream.Flush(); stream.Flush();
} }

Просмотреть файл

@ -42,6 +42,7 @@ public interface LibraryVMInterface
void jniWaitUntilLastThread(); void jniWaitUntilLastThread();
void jniDetach(); void jniDetach();
void setThreadGroup(Object group);
Object newConstructor(Object clazz, Object wrapper); Object newConstructor(Object clazz, Object wrapper);
Object newMethod(Object clazz, Object wrapper); Object newMethod(Object clazz, Object wrapper);

Просмотреть файл

@ -1,9 +1,35 @@
/*
Copyright (C) 2003, 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
package ikvm.lang; package ikvm.lang;
/** @deprecated */
public final class ByteArrayHack public final class ByteArrayHack
{ {
private ByteArrayHack() {} private ByteArrayHack() {}
public static native cli.System.Byte[] cast(byte[] b); public static byte[] cast(byte[] b)
public static native byte[] cast(cli.System.Byte[] b); {
return b;
}
} }

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2003, 2004 Jeroen Frijters Copyright (C) 2003, 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -43,12 +43,12 @@ public class CIL
public static native Object box_long(long v); public static native Object box_long(long v);
public static native Object box_double(double v); public static native Object box_double(double v);
public static native cli.System.Byte box_ubyte(byte v); public static native cli.System.SByte box_sbyte(byte v);
public static native cli.System.UInt16 box_ushort(short 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.UInt32 box_uint(int v);
public static native cli.System.UInt64 box_ulong(long v); public static native cli.System.UInt64 box_ulong(long v);
public static native byte unbox_ubyte(cli.System.Byte v); public static native byte unbox_sbyte(cli.System.SByte v);
public static native short unbox_ushort(cli.System.UInt16 v); public static native short unbox_ushort(cli.System.UInt16 v);
public static native int unbox_uint(cli.System.UInt32 v); public static native int unbox_uint(cli.System.UInt32 v);
public static native long unbox_ulong(cli.System.UInt64 v); public static native long unbox_ulong(cli.System.UInt64 v);

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2004 Jeroen Frijters Copyright (C) 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -91,7 +91,7 @@ class LibraryVMInterfaceImpl implements ikvm.internal.LibraryVMInterface
public Object box(Object val) public Object box(Object val)
{ {
if(val instanceof cli.System.SByte) if(val instanceof cli.System.Byte)
{ {
return new Byte(CIL.unbox_byte(val)); return new Byte(CIL.unbox_byte(val));
} }
@ -189,12 +189,17 @@ class LibraryVMInterfaceImpl implements ikvm.internal.LibraryVMInterface
VMThread.jniDetach(); VMThread.jniDetach();
} }
public void setThreadGroup(Object group)
{
VMThread.setThreadGroup((ThreadGroup)group);
}
public native Object newDirectByteBuffer(cli.System.IntPtr address, int capacity); public native Object newDirectByteBuffer(cli.System.IntPtr address, int capacity);
public native cli.System.IntPtr getDirectBufferAddress(Object buffer); public native cli.System.IntPtr getDirectBufferAddress(Object buffer);
public int getDirectBufferCapacity(Object buffer) public int getDirectBufferCapacity(Object buffer)
{ {
return ((java.nio.ByteBuffer)buffer).capacity(); return ((java.nio.Buffer)buffer).capacity();
} }
public void setProperties(cli.System.Collections.Hashtable props) public void setProperties(cli.System.Collections.Hashtable props)

Просмотреть файл

@ -45,6 +45,7 @@ import java.util.Enumeration;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import gnu.classpath.SystemProperties; import gnu.classpath.SystemProperties;
@ -173,31 +174,34 @@ final class VMClassLoader
*/ */
static Enumeration getResources(String name) throws IOException static Enumeration getResources(String name) throws IOException
{ {
if(cli.System.Threading.Thread.GetData(nestedGetResourcesHack) != null) synchronized(nestedGetResourcesHack)
{ {
return gnu.java.util.EmptyEnumeration.getInstance(); if(cli.System.Threading.Thread.GetData(nestedGetResourcesHack) != null)
}
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, "");
try
{
Assembly[] assemblies = findResourceAssemblies(name);
java.util.Vector v = new java.util.Vector();
for(int i = 0; i < assemblies.length; i++)
{ {
v.addElement(new URL("ikvmres", assemblies[i].get_FullName(), -1, "/" + name)); return gnu.java.util.EmptyEnumeration.getInstance();
} }
Enumeration e = v.elements(); cli.System.Threading.Thread.SetData(nestedGetResourcesHack, "");
ClassLoader bootstrap = getBootstrapClassLoader(); try
if(bootstrap != null)
{ {
e = new DoubleEnumeration(e, bootstrap.getResources(name)); Assembly[] assemblies = findResourceAssemblies(name);
java.util.Vector v = new java.util.Vector();
for(int i = 0; i < assemblies.length; i++)
{
v.addElement(new URL("ikvmres", assemblies[i].get_FullName(), -1, "/" + name));
}
Enumeration e = v.elements();
ClassLoader bootstrap = getBootstrapClassLoader();
if(bootstrap != null)
{
e = new DoubleEnumeration(e, bootstrap.getResources(name));
}
return e;
} }
return e; finally
} {
finally cli.System.Threading.Thread.SetData(nestedGetResourcesHack, null);
{ }
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, null); }
}
} }
private static cli.System.LocalDataStoreSlot nestedGetResourcesHack = cli.System.Threading.Thread.AllocateDataSlot(); private static cli.System.LocalDataStoreSlot nestedGetResourcesHack = cli.System.Threading.Thread.AllocateDataSlot();
@ -212,6 +216,14 @@ final class VMClassLoader
*/ */
static Package getPackage(String name) static Package getPackage(String name)
{ {
Package[] packages = getPackagesImpl();
for(int i = 0; i < packages.length; i++)
{
if(packages[i].getName().equals(name))
{
return packages[i];
}
}
return null; return null;
} }
@ -224,9 +236,96 @@ final class VMClassLoader
*/ */
static Package[] getPackages() static Package[] getPackages()
{ {
return new Package[0]; return (Package[])getPackagesImpl().clone();
} }
private static boolean runningOnMono = Type.GetType("Mono.Runtime") != null;
private static Package[] getPackagesImpl()
{
// MONOBUG Assembly.GetTypes() on IKVM.GNU.Classpath dies
if(runningOnMono)
{
return new Package[0];
}
Package[] packages = packageCache;
if(packages == null)
{
ClassLoader boot = getBootstrapClassLoader();
if(boot != null)
{
synchronized(nestedGetResourcesHack)
{
if(cli.System.Threading.Thread.GetData(nestedGetResourcesHack) != null)
{
return new Package[0];
}
}
}
HashMap h = new HashMap();
Assembly[] assemblies = AppDomain.get_CurrentDomain().GetAssemblies();
for(int i = 0; i < assemblies.length; i++)
{
if(!(assemblies[i] instanceof cli.System.Reflection.Emit.AssemblyBuilder))
{
Type[] types = assemblies[i].GetTypes();
for(int j = 0; j < types.length; j++)
{
String name = getPackageName(types[j]);
if(name != null)
{
// TODO fill out more package details
h.put(name, new Package(name, null, null, null, null, null, null, null));
}
}
}
}
if(boot != null)
{
Package[] pkgboot;
synchronized(nestedGetResourcesHack)
{
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, "");
try
{
pkgboot = boot.getPackages();
}
finally
{
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, null);
}
}
Collection c = h.values();
packages = new Package[c.size() + pkgboot.length];
c.toArray(packages);
VMSystem.arraycopy(pkgboot, 0, packages, c.size(), pkgboot.length);
// we don't cache the result, because we don't know when the bootstrap class loader loads a new package
}
else
{
Collection c = h.values();
packages = new Package[c.size()];
c.toArray(packages);
packageCache = packages;
}
}
return packages;
}
private static volatile Package[] packageCache;
static
{
AppDomain.get_CurrentDomain().add_AssemblyLoad(new AssemblyLoadEventHandler(
new AssemblyLoadEventHandler.Method() {
public void Invoke(Object sender, AssemblyLoadEventArgs args) {
packageCache = null;
}
}));
}
private static native String getPackageName(Type type);
/** /**
* Helper for java.lang.Integer, Byte, etc to get the TYPE class * Helper for java.lang.Integer, Byte, etc to get the TYPE class
* at initialization time. The type code is one of the chars that * at initialization time. The type code is one of the chars that

Просмотреть файл

@ -189,7 +189,7 @@ final class VMRuntime
* @param filename the file to load * @param filename the file to load
* @return 0 on failure, nonzero on success * @return 0 on failure, nonzero on success
*/ */
static native int nativeLoad(String filename); static native int nativeLoad(String filename, Object classLoader);
/** /**
* Map a system-independent "short name" to the full file name. * Map a system-independent "short name" to the full file name.

Просмотреть файл

@ -161,6 +161,15 @@ final class VMThread
} }
} }
static void setThreadGroup(ThreadGroup group)
{
Thread javaThread = (Thread)cli.System.Threading.Thread.GetData(localDataStoreSlot);
if(javaThread == null)
{
newThread(group);
}
}
static void create(Thread thread, long stacksize) static void create(Thread thread, long stacksize)
{ {
VMThread vmThread = new VMThread(thread); VMThread vmThread = new VMThread(thread);
@ -463,50 +472,56 @@ final class VMThread
} }
} }
// this method creates a new java.lang.Thread instance for threads that were started outside
// of Java (either in .NET or in native code)
private static Thread newThread(ThreadGroup group)
{
cli.System.Threading.Thread nativeThread = cli.System.Threading.Thread.get_CurrentThread();
VMThread vmThread = new VMThread(null);
vmThread.nativeThreadReference = new cli.System.WeakReference(nativeThread);
vmThread.running = true;
int priority = Thread.NORM_PRIORITY;
switch(nativeThread.get_Priority().Value)
{
case cli.System.Threading.ThreadPriority.Lowest:
priority = Thread.MIN_PRIORITY;
break;
case cli.System.Threading.ThreadPriority.BelowNormal:
priority = 3;
break;
case cli.System.Threading.ThreadPriority.Normal:
priority = Thread.NORM_PRIORITY;
break;
case cli.System.Threading.ThreadPriority.AboveNormal:
priority = 7;
break;
case cli.System.Threading.ThreadPriority.Highest:
priority = Thread.MAX_PRIORITY;
break;
}
Thread javaThread = new Thread(vmThread, nativeThread.get_Name(), priority, nativeThread.get_IsBackground());
if(!javaThread.daemon)
{
synchronized(countLock)
{
nonDaemonCount++;
}
}
vmThread.thread = javaThread;
cli.System.Threading.Thread.SetData(localDataStoreSlot, javaThread);
cli.System.Threading.Thread.SetData(cli.System.Threading.Thread.GetNamedDataSlot("ikvm-thread-hack"), new CleanupHack(javaThread));
javaThread.group = group;
javaThread.group.addThread(javaThread);
InheritableThreadLocal.newChildThread(javaThread);
return javaThread;
}
static Thread currentThread() static Thread currentThread()
{ {
Thread javaThread = (Thread)cli.System.Threading.Thread.GetData(localDataStoreSlot); Thread javaThread = (Thread)cli.System.Threading.Thread.GetData(localDataStoreSlot);
if(javaThread == null) if(javaThread == null)
{ {
cli.System.Threading.Thread nativeThread = cli.System.Threading.Thread.get_CurrentThread(); javaThread = newThread(ThreadGroup.root);
VMThread vmThread = new VMThread(null);
vmThread.nativeThreadReference = new cli.System.WeakReference(nativeThread);
vmThread.running = true;
int priority = Thread.NORM_PRIORITY;
switch(nativeThread.get_Priority().Value)
{
case cli.System.Threading.ThreadPriority.Lowest:
priority = Thread.MIN_PRIORITY;
break;
case cli.System.Threading.ThreadPriority.BelowNormal:
priority = 3;
break;
case cli.System.Threading.ThreadPriority.Normal:
priority = Thread.NORM_PRIORITY;
break;
case cli.System.Threading.ThreadPriority.AboveNormal:
priority = 7;
break;
case cli.System.Threading.ThreadPriority.Highest:
priority = Thread.MAX_PRIORITY;
break;
}
javaThread = new Thread(vmThread, nativeThread.get_Name(), priority, nativeThread.get_IsBackground());
if(!javaThread.daemon)
{
synchronized(countLock)
{
nonDaemonCount++;
}
}
vmThread.thread = javaThread;
cli.System.Threading.Thread.SetData(localDataStoreSlot, javaThread);
cli.System.Threading.Thread.SetData(cli.System.Threading.Thread.GetNamedDataSlot("ikvm-thread-hack"), new CleanupHack(javaThread));
// HACK JNI code can attach native threads to any thread group
ThreadGroup group = (ThreadGroup)cli.System.Threading.Thread.GetData(cli.System.Threading.Thread.GetNamedDataSlot("ikvm-thread-group"));
javaThread.group = group == null ? ThreadGroup.root : group;
javaThread.group.addThread(javaThread);
InheritableThreadLocal.newChildThread(javaThread);
} }
return javaThread; return javaThread;
} }

Просмотреть файл

@ -39,6 +39,7 @@ exception statement from your version. */
package java.lang.reflect; package java.lang.reflect;
import cli.System.Diagnostics.StackFrame; import cli.System.Diagnostics.StackFrame;
import gnu.classpath.VMStackWalker;
/** /**
* The Constructor class represents a constructor of a class. It also allows * The Constructor class represents a constructor of a class. It also allows
@ -259,7 +260,7 @@ public final class Constructor
InvocationTargetException InvocationTargetException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
Field.checkAccess(modifiers, null, declaringClass, new StackFrame(1)); Field.checkAccess(modifiers, null, declaringClass, VMStackWalker.getCallingClass());
int mods = declaringClass.getModifiers() | Method.GetRealModifiers(declaringClass); int mods = declaringClass.getModifiers() | Method.GetRealModifiers(declaringClass);
if(Modifier.isAbstract(mods) || Modifier.isInterface(mods)) if(Modifier.isAbstract(mods) || Modifier.isInterface(mods))
{ {

Просмотреть файл

@ -39,6 +39,7 @@ exception statement from your version. */
package java.lang.reflect; package java.lang.reflect;
import cli.System.Diagnostics.StackFrame; import cli.System.Diagnostics.StackFrame;
import gnu.classpath.VMStackWalker;
/** /**
* The Field class represents a member variable of a class. It also allows * The Field class represents a member variable of a class. It also allows
@ -236,7 +237,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return GetValue(fieldCookie, o); return GetValue(fieldCookie, o);
} }
private static native Object GetValue(Object fieldCookie, Object o); private static native Object GetValue(Object fieldCookie, Object o);
@ -262,7 +263,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return ((Boolean)GetValue(fieldCookie, o)).booleanValue(); return ((Boolean)GetValue(fieldCookie, o)).booleanValue();
} }
@ -287,7 +288,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return ((Byte)GetValue(fieldCookie, o)).byteValue(); return ((Byte)GetValue(fieldCookie, o)).byteValue();
} }
@ -310,7 +311,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return ((Character)GetValue(fieldCookie, o)).charValue(); return ((Character)GetValue(fieldCookie, o)).charValue();
} }
@ -335,7 +336,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return ((Short)GetValue(fieldCookie, o)).shortValue(); return ((Short)GetValue(fieldCookie, o)).shortValue();
} }
@ -360,7 +361,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return ((Integer)GetValue(fieldCookie, o)).intValue(); return ((Integer)GetValue(fieldCookie, o)).intValue();
} }
@ -385,7 +386,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return ((Long)GetValue(fieldCookie, o)).longValue(); return ((Long)GetValue(fieldCookie, o)).longValue();
} }
@ -410,7 +411,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return ((Float)GetValue(fieldCookie, o)).floatValue(); return ((Float)GetValue(fieldCookie, o)).floatValue();
} }
@ -436,7 +437,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return ((Double)GetValue(fieldCookie, o)).doubleValue(); return ((Double)GetValue(fieldCookie, o)).doubleValue();
} }
@ -489,17 +490,16 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, value); SetValue(fieldCookie, o, value);
} }
private static native void SetValue(Object fieldCookie, Object o, Object value); private static native void SetValue(Object fieldCookie, Object o, Object value);
static void checkAccess(int modifiers, Object o, Class declaringClass, StackFrame frame) throws IllegalAccessException static void checkAccess(int modifiers, Object o, Class declaringClass, Class caller) throws IllegalAccessException
{ {
// when we're invoking a constructor, modifiers will not be static, but o will be null. // when we're invoking a constructor, modifiers will not be static, but o will be null.
Class actualClass = Modifier.isStatic(modifiers) || o == null ? declaringClass : o.getClass(); Class actualClass = Modifier.isStatic(modifiers) || o == null ? declaringClass : o.getClass();
boolean declaringClassIsPublic = (Method.GetRealModifiers(declaringClass) & Modifier.PUBLIC) != 0; boolean declaringClassIsPublic = (Method.GetRealModifiers(declaringClass) & Modifier.PUBLIC) != 0;
Class caller = getClassFromFrame(frame);
if((!Modifier.isPublic(modifiers) || !declaringClassIsPublic) && declaringClass != caller) if((!Modifier.isPublic(modifiers) || !declaringClassIsPublic) && declaringClass != caller)
{ {
// if the caller is a global method, the class returned will be null // if the caller is a global method, the class returned will be null
@ -512,12 +512,13 @@ public final class Field extends AccessibleObject implements Member
} }
else if(!isSamePackage(declaringClass, caller) || Modifier.isPrivate(modifiers)) else if(!isSamePackage(declaringClass, caller) || Modifier.isPrivate(modifiers))
{ {
throw new IllegalAccessException(); throw new IllegalAccessException("Class " + caller.getName() +
" can not access a member of class " + declaringClass.getName() +
" with modifiers \"" + Modifier.toString(modifiers & (Modifier.PRIVATE | Modifier.PROTECTED)) + "\"");
} }
} }
} }
private static native boolean isSamePackage(Class a, Class b); private static native boolean isSamePackage(Class a, Class b);
private static native Class getClassFromFrame(StackFrame frame);
/** /**
* Set this boolean Field. If the field is static, <code>o</code> will be * Set this boolean Field. If the field is static, <code>o</code> will be
@ -540,7 +541,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, new Boolean(value)); SetValue(fieldCookie, o, new Boolean(value));
} }
@ -565,7 +566,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, new Byte(value)); SetValue(fieldCookie, o, new Byte(value));
} }
@ -590,7 +591,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, new Character(value)); SetValue(fieldCookie, o, new Character(value));
} }
@ -615,7 +616,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, new Short(value)); SetValue(fieldCookie, o, new Short(value));
} }
@ -640,7 +641,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, new Integer(value)); SetValue(fieldCookie, o, new Integer(value));
} }
@ -665,7 +666,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, new Long(value)); SetValue(fieldCookie, o, new Long(value));
} }
@ -690,7 +691,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, new Float(value)); SetValue(fieldCookie, o, new Float(value));
} }
@ -715,7 +716,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException throws IllegalAccessException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1)); checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, new Double(value)); SetValue(fieldCookie, o, new Double(value));
} }
} }

Просмотреть файл

@ -39,6 +39,7 @@ exception statement from your version. */
package java.lang.reflect; package java.lang.reflect;
import cli.System.Diagnostics.StackFrame; import cli.System.Diagnostics.StackFrame;
import gnu.classpath.VMStackWalker;
/** /**
* The Method class represents a member method of a class. It also allows * The Method class represents a member method of a class. It also allows
@ -336,7 +337,7 @@ public final class Method extends AccessibleObject implements Member
throws IllegalAccessException, InvocationTargetException throws IllegalAccessException, InvocationTargetException
{ {
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic)) if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
Field.checkAccess(modifiers, o, declaringClass, new StackFrame(1)); Field.checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
if(!Modifier.isStatic(modifiers)) if(!Modifier.isStatic(modifiers))
{ {
if(o == null) if(o == null)

Просмотреть файл

@ -1,3 +1,26 @@
/*
Copyright (C) 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
package java.nio; package java.nio;
import gnu.classpath.RawData; import gnu.classpath.RawData;
@ -12,9 +35,9 @@ class VMDirectByteBuffer
return new DirectByteBufferImpl.ReadWrite(null, new RawData(p), capacity, capacity, 0); return new DirectByteBufferImpl.ReadWrite(null, new RawData(p), capacity, capacity, 0);
} }
static IntPtr GetDirectBufferAddress(ByteBuffer buf) static IntPtr GetDirectBufferAddress(Buffer buf)
{ {
return ((DirectByteBufferImpl)buf).address.p(); return buf.address != null ? buf.address.p() : IntPtr.Zero;
} }
static RawData allocate(int capacity) static RawData allocate(int capacity)
@ -35,7 +58,7 @@ class VMDirectByteBuffer
static void get(RawData r, int index, byte[] dst, int offset, int length) static void get(RawData r, int index, byte[] dst, int offset, int length)
{ {
IntPtr address = new IntPtr(r.p().ToInt64() + index); IntPtr address = new IntPtr(r.p().ToInt64() + index);
Marshal.Copy(address, ikvm.lang.ByteArrayHack.cast(dst), offset, length); Marshal.Copy(address, dst, offset, length);
} }
static void put(RawData r, int index, byte value) static void put(RawData r, int index, byte value)

Просмотреть файл

@ -0,0 +1,56 @@
/*
Copyright (C) 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
package java.nio.channels;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import gnu.java.nio.ChannelInputStream;
import gnu.java.nio.ChannelOutputStream;
import gnu.java.nio.channels.FileChannelImpl;
final class VMChannels
{
// These methods are implemented in map.xml, because they rely on a package private
// constructor of FileInputStream and FileOutputStream.
private static native FileInputStream newInputStream(FileChannelImpl ch);
private static native FileOutputStream newOutputStream(FileChannelImpl ch);
static InputStream newInputStream(ReadableByteChannel ch)
{
if (ch instanceof FileChannelImpl)
return newInputStream((FileChannelImpl)ch);
else
return new ChannelInputStream(ch);
}
static OutputStream newOutputStream(WritableByteChannel ch)
{
if (ch instanceof FileChannelImpl)
return newOutputStream((FileChannelImpl)ch);
else
return new ChannelOutputStream(ch);
}
}

Просмотреть файл

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<!-- <!--
Copyright (C) 2002, 2003, 2004 Jeroen Frijters Copyright (C) 2002, 2003, 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -205,6 +205,17 @@
<constructor sig="(Ljava.lang.StringBuffer;)V" modifiers="public"> <constructor sig="(Ljava.lang.StringBuffer;)V" modifiers="public">
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="(Ljava.lang.StringBuffer;)Ljava.lang.String;" /> <redirect class="java.lang.StringHelper" name="NewString" type="static" sig="(Ljava.lang.StringBuffer;)Ljava.lang.String;" />
</constructor> </constructor>
<constructor sig="(Ljava.lang.StringBuilder;)V" modifiers="public">
<alternateBody>
<ldarg_0 />
<ldfld class="java.lang.StringBuilder" name="value" sig="[C" />
<ldc_i4_0 />
<ldarg_0 />
<ldfld class="java.lang.StringBuilder" name="count" sig="I" />
<newobj type="System.String, mscorlib" name=".ctor" sig="([CII)V" />
<ret />
</alternateBody>
</constructor>
<constructor sig="([B)V" modifiers="public"> <constructor sig="([B)V" modifiers="public">
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([B)Ljava.lang.String;" /> <redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([B)Ljava.lang.String;" />
</constructor> </constructor>
@ -644,7 +655,7 @@
<method name="unbox_byte" sig="(Ljava.lang.Object;)B"> <method name="unbox_byte" sig="(Ljava.lang.Object;)B">
<body> <body>
<ldarg_0 /> <ldarg_0 />
<unbox type="System.SByte, mscorlib" /> <unbox type="System.Byte, mscorlib" />
<ldind_i1 /> <ldind_i1 />
<ret /> <ret />
</body> </body>
@ -708,7 +719,7 @@
<method name="box_byte" sig="(B)Ljava.lang.Object;"> <method name="box_byte" sig="(B)Ljava.lang.Object;">
<body> <body>
<ldarg_0 /> <ldarg_0 />
<box type="System.SByte, mscorlib" /> <box type="System.Byte, mscorlib" />
<ret /> <ret />
</body> </body>
</method> </method>
@ -761,7 +772,7 @@
<ret /> <ret />
</body> </body>
</method> </method>
<method name="box_ubyte" sig="(B)Lcli.System.Byte;"> <method name="box_sbyte" sig="(B)Lcli.System.SByte;">
<body> <body>
<ldarg_0 /> <ldarg_0 />
<ret /> <ret />
@ -785,7 +796,7 @@
<ret /> <ret />
</body> </body>
</method> </method>
<method name="unbox_ubyte" sig="(Lcli.System.Byte;)B"> <method name="unbox_sbyte" sig="(Lcli.System.SByte;)B">
<body> <body>
<ldarg_0 /> <ldarg_0 />
<ret /> <ret />
@ -810,20 +821,6 @@
</body> </body>
</method> </method>
</class> </class>
<class name="ikvm.lang.ByteArrayHack">
<method name="cast" sig="([B)[Lcli.System.Byte;">
<body>
<ldarg_0 />
<ret />
</body>
</method>
<method name="cast" sig="([Lcli.System.Byte;)[B">
<body>
<ldarg_0 />
<ret />
</body>
</method>
</class>
<class name="java.lang.VMClass"> <class name="java.lang.VMClass">
<method name="createField" sig="(Ljava.lang.Class;Ljava.lang.Object;)Ljava.lang.reflect.Field;"> <method name="createField" sig="(Ljava.lang.Class;Ljava.lang.Object;)Ljava.lang.reflect.Field;">
<body> <body>
@ -883,11 +880,8 @@
<method name="getDirectBufferAddress" sig="(Ljava.lang.Object;)Lcli.System.IntPtr;"> <method name="getDirectBufferAddress" sig="(Ljava.lang.Object;)Lcli.System.IntPtr;">
<body> <body>
<ldarg_1 /> <ldarg_1 />
<castclass class="java.nio.ByteBuffer" /> <castclass class="java.nio.Buffer" />
<call class="java.nio.VMDirectByteBuffer" name="GetDirectBufferAddress" sig="(Ljava.nio.ByteBuffer;)Lcli.System.IntPtr;" /> <call class="java.nio.VMDirectByteBuffer" name="GetDirectBufferAddress" sig="(Ljava.nio.Buffer;)Lcli.System.IntPtr;" />
<!-- LAME we need to unbox the return value -->
<unbox type="System.IntPtr, mscorlib" />
<ldobj type="System.IntPtr, mscorlib" />
<ret /> <ret />
</body> </body>
</method> </method>
@ -909,7 +903,7 @@
</body> </body>
</method> </method>
</class> </class>
<class name="java.nio.channels.Channels"> <class name="java.nio.channels.VMChannels">
<method name="newInputStream" sig="(Lgnu.java.nio.channels.FileChannelImpl;)Ljava.io.FileInputStream;"> <method name="newInputStream" sig="(Lgnu.java.nio.channels.FileChannelImpl;)Ljava.io.FileInputStream;">
<body> <body>
<ldarg_0 /> <ldarg_0 />
@ -938,7 +932,7 @@
<ldarg_0 /> <ldarg_0 />
<ldfld class="java.nio.Buffer" name="pos" sig="I" /> <ldfld class="java.nio.Buffer" name="pos" sig="I" />
<call type="gnu.classpath.RawData" name="ReadByte" sig="(I)B" /> <call type="gnu.classpath.RawData" name="ReadByte" sig="(I)B" />
<stloc name="result" type="System.SByte, mscorlib" /> <stloc name="result" type="System.Byte, mscorlib" />
<ldarg_0 /> <ldarg_0 />
<ldarg_0 /> <ldarg_0 />
<ldfld class="java.nio.Buffer" name="pos" sig="I" /> <ldfld class="java.nio.Buffer" name="pos" sig="I" />

Двоичные данные
classpath/mscorlib.jar

Двоичный файл не отображается.

Просмотреть файл

@ -49,7 +49,7 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("0.10.0.1")] [assembly: AssemblyVersion("0.11.*")]
// //
// In order to sign your assembly you must specify a key to use. Refer to the // In order to sign your assembly you must specify a key to use. Refer to the

Просмотреть файл

@ -49,7 +49,7 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("0.10.0.1")] [assembly: AssemblyVersion("0.11.*")]
// //
// In order to sign your assembly you must specify a key to use. Refer to the // In order to sign your assembly you must specify a key to use. Refer to the

Просмотреть файл

@ -49,7 +49,7 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("0.10.0.1")] [assembly: AssemblyVersion("0.11.*")]
// //
// In order to sign your assembly you must specify a key to use. Refer to the // In order to sign your assembly you must specify a key to use. Refer to the

Просмотреть файл

@ -724,9 +724,9 @@ class ClassFileWriter
if(constantValue != null) if(constantValue != null)
{ {
ushort constantValueIndex; ushort constantValueIndex;
if(constantValue is sbyte) if(constantValue is byte)
{ {
constantValueIndex = AddInt((sbyte)constantValue); constantValueIndex = AddInt((sbyte)(byte)constantValue);
} }
else if(constantValue is bool) else if(constantValue is bool)
{ {
@ -744,18 +744,10 @@ class ClassFileWriter
{ {
constantValueIndex = AddInt((int)constantValue); constantValueIndex = AddInt((int)constantValue);
} }
else if(constantValue is uint)
{
constantValueIndex = AddInt((int)(uint)constantValue);
}
else if(constantValue is long) else if(constantValue is long)
{ {
constantValueIndex = AddLong((long)constantValue); constantValueIndex = AddLong((long)constantValue);
} }
else if(constantValue is ulong)
{
constantValueIndex = AddLong((long)(ulong)constantValue);
}
else if(constantValue is float) else if(constantValue is float)
{ {
constantValueIndex = AddFloat((float)constantValue); constantValueIndex = AddFloat((float)constantValue);

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2002, 2004 Jeroen Frijters Copyright (C) 2002, 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -27,8 +27,6 @@ using System.IO;
using System.Text; using System.Text;
using System.Collections; using System.Collections;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using java.lang;
using java.lang.reflect;
using IKVM.Attributes; using IKVM.Attributes;
using IKVM.Internal; using IKVM.Internal;
@ -79,6 +77,7 @@ public class NetExp
{ {
assembly = Assembly.LoadWithPartialName(args[0]); assembly = Assembly.LoadWithPartialName(args[0]);
} }
int rc = 0;
if(assembly == null) if(assembly == null)
{ {
Console.Error.WriteLine("Error: Assembly \"{0}\" not found", args[0]); Console.Error.WriteLine("Error: Assembly \"{0}\" not found", args[0]);
@ -94,12 +93,13 @@ public class NetExp
catch(System.Exception x) catch(System.Exception x)
{ {
java.lang.Throwable.instancehelper_printStackTrace(IKVM.Runtime.Util.MapException(x)); java.lang.Throwable.instancehelper_printStackTrace(IKVM.Runtime.Util.MapException(x));
rc = 1;
} }
zipFile.Close(); zipFile.Close();
} }
// FXBUG if we run a static initializer that starts a thread, we would never end, // FXBUG if we run a static initializer that starts a thread, we would never end,
// so we force an exit here // so we force an exit here
Environment.Exit(0); Environment.Exit(rc);
} }
private static void WriteClass(string name, ClassFileWriter c) private static void WriteClass(string name, ClassFileWriter c)
@ -114,12 +114,12 @@ public class NetExp
{ {
if(t.IsPublic) if(t.IsPublic)
{ {
Class c; java.lang.Class c;
try try
{ {
c = Class.forName(t.AssemblyQualifiedName, false, null); c = java.lang.Class.forName(t.AssemblyQualifiedName, false, null);
} }
catch(ClassNotFoundException) catch(java.lang.ClassNotFoundException)
{ {
// types that IKVM doesn't support don't show up // types that IKVM doesn't support don't show up
continue; continue;
@ -139,7 +139,7 @@ public class NetExp
Hashtable todo = privateClasses; Hashtable todo = privateClasses;
privateClasses = new Hashtable(); privateClasses = new Hashtable();
keepGoing = false; keepGoing = false;
foreach(Class c in todo.Values) foreach(java.lang.Class c in todo.Values)
{ {
if(!done.ContainsKey(c.getName())) if(!done.ContainsKey(c.getName()))
{ {
@ -151,7 +151,7 @@ public class NetExp
} while(keepGoing); } while(keepGoing);
} }
private static void ProcessClass(string assemblyName, Class c, Class outer) private static void ProcessClass(string assemblyName, java.lang.Class c, java.lang.Class outer)
{ {
string name = c.getName().Replace('.', '/'); string name = c.getName().Replace('.', '/');
string super = null; string super = null;
@ -159,7 +159,7 @@ public class NetExp
{ {
super = c.getSuperclass().getName().Replace('.', '/'); super = c.getSuperclass().getName().Replace('.', '/');
// if the base class isn't public, we still need to export it (!) // if the base class isn't public, we still need to export it (!)
if(!Modifier.isPublic(c.getSuperclass().getModifiers())) if(!java.lang.reflect.Modifier.isPublic(c.getSuperclass().getModifiers()))
{ {
privateClasses[c.getSuperclass().getName()] = c.getSuperclass(); privateClasses[c.getSuperclass().getName()] = c.getSuperclass();
} }
@ -196,15 +196,15 @@ public class NetExp
} }
innerClassesAttribute.Add(name, outer.getName().Replace('.', '/'), innername, (ushort)c.getModifiers()); innerClassesAttribute.Add(name, outer.getName().Replace('.', '/'), innername, (ushort)c.getModifiers());
} }
Class[] interfaces = c.getInterfaces(); java.lang.Class[] interfaces = c.getInterfaces();
for(int i = 0; i < interfaces.Length; i++) for(int i = 0; i < interfaces.Length; i++)
{ {
if(Modifier.isPublic(interfaces[i].getModifiers())) if(java.lang.reflect.Modifier.isPublic(interfaces[i].getModifiers()))
{ {
f.AddInterface(interfaces[i].getName().Replace('.', '/')); f.AddInterface(interfaces[i].getName().Replace('.', '/'));
} }
} }
Class[] innerClasses = c.getDeclaredClasses(); java.lang.Class[] innerClasses = c.getDeclaredClasses();
for(int i = 0; i < innerClasses.Length; i++) for(int i = 0; i < innerClasses.Length; i++)
{ {
Modifiers mods = (Modifiers)innerClasses[i].getModifiers(); Modifiers mods = (Modifiers)innerClasses[i].getModifiers();
@ -220,7 +220,7 @@ public class NetExp
ProcessClass(assemblyName, innerClasses[i], c); ProcessClass(assemblyName, innerClasses[i], c);
} }
} }
Constructor[] constructors = c.getDeclaredConstructors(); java.lang.reflect.Constructor[] constructors = c.getDeclaredConstructors();
for(int i = 0; i < constructors.Length; i++) for(int i = 0; i < constructors.Length; i++)
{ {
Modifiers mods = (Modifiers)constructors[i].getModifiers(); Modifiers mods = (Modifiers)constructors[i].getModifiers();
@ -250,7 +250,7 @@ public class NetExp
} }
} }
} }
Method[] methods = c.getDeclaredMethods(); java.lang.reflect.Method[] methods = c.getDeclaredMethods();
for(int i = 0; i < methods.Length; i++) for(int i = 0; i < methods.Length; i++)
{ {
Modifiers mods = (Modifiers)methods[i].getModifiers(); Modifiers mods = (Modifiers)methods[i].getModifiers();
@ -269,7 +269,7 @@ public class NetExp
} }
} }
} }
Field[] fields = c.getDeclaredFields(); java.lang.reflect.Field[] fields = c.getDeclaredFields();
for(int i = 0; i < fields.Length; i++) for(int i = 0; i < fields.Length; i++)
{ {
Modifiers mods = (Modifiers)fields[i].getModifiers(); Modifiers mods = (Modifiers)fields[i].getModifiers();
@ -340,12 +340,12 @@ public class NetExp
WriteClass(name + ".class", f); WriteClass(name + ".class", f);
} }
private static void AddExceptions(ClassFileWriter f, FieldOrMethod m, Class[] exceptions) private static void AddExceptions(ClassFileWriter f, FieldOrMethod m, java.lang.Class[] exceptions)
{ {
if(exceptions.Length > 0) if(exceptions.Length > 0)
{ {
ExceptionsAttribute attrib = new ExceptionsAttribute(f); ExceptionsAttribute attrib = new ExceptionsAttribute(f);
foreach(Class x in exceptions) foreach(java.lang.Class x in exceptions)
{ {
// TODO what happens if one of the exception types is non-public? // TODO what happens if one of the exception types is non-public?
attrib.Add(x.getName().Replace('.', '/')); attrib.Add(x.getName().Replace('.', '/'));
@ -354,7 +354,7 @@ public class NetExp
} }
} }
private static string MakeSig(Class[] args, Class ret) private static string MakeSig(java.lang.Class[] args, java.lang.Class ret)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.Append('('); sb.Append('(');
@ -367,7 +367,7 @@ public class NetExp
return sb.ToString(); return sb.ToString();
} }
private static string ClassToSig(Class c) private static string ClassToSig(java.lang.Class c)
{ {
if(c.isPrimitive()) if(c.isPrimitive())
{ {

Просмотреть файл

@ -8,7 +8,7 @@
<property name="REFERENCE_API_NAME" value="JDK-1.5" /> <property name="REFERENCE_API_NAME" value="JDK-1.5" />
--> -->
<property name="JAPI_HOME" value="c:\japi\japitools" /> <property name="JAPI_HOME" value="c:\japi\japitools" />
<property name="IKVM_VERSION" value="0.10.0.0" /> <property name="IKVM_VERSION" value="0.11.0.0" />
<target name="default"> <target name="default">
<call target="status" /> <call target="status" />

Просмотреть файл

@ -23,12 +23,9 @@
*/ */
.assembly JVM .assembly JVM
{ {
.ver 0:10:0:1 .ver 0:11:0:0
} }
.module JVM.DLL .module JVM.DLL
.corflags 0x00000002
.vtfixup [3] int32 fromunmanaged at VTable
.data VTable = int32[3]
.method public static int32 JNI_CreateJavaVM(void* ppvm, void* ppenv, void* args) .method public static int32 JNI_CreateJavaVM(void* ppvm, void* ppenv, void* args)
{ {

Просмотреть файл

@ -3,6 +3,9 @@
<target name="JVM"> <target name="JVM">
<property overwrite="false" name="ilasm_signoption" value="" /> <property overwrite="false" name="ilasm_signoption" value="" />
<exec program="../tools/asmref.exe" useruntimeengine="true" commandline="mscorlib ../bin/IKVM.Runtime.dll ../bin/IKVM.GNU.Classpath.dll" output="jvm_h.il" /> <exec program="../tools/asmref.exe" useruntimeengine="true" commandline="mscorlib ../bin/IKVM.Runtime.dll ../bin/IKVM.GNU.Classpath.dll" output="jvm_h.il" />
<exec program="ilasm" commandline="/dll ${ilasm_signoption} /out:../bin/JVM.DLL jvm_h.il JVM.il" /> <exec program="ilasm" commandline="/dll ${ilasm_signoption} /out:../bin/JVM.DLL jvm_h.il jvm32.il JVM.il" />
<!--
<exec program="ilasm" commandline="/x64 /dll ${ilasm_signoption} /out:../bin/JVM.DLL jvm_h.il jvm64.il JVM.il" />
-->
</target> </target>
</project> </project>

3
jvm/jvm32.il Normal file
Просмотреть файл

@ -0,0 +1,3 @@
.corflags 0x00000002
.vtfixup [3] int32 fromunmanaged at VTable
.data VTable = int32[3]

2
jvm/jvm64.il Normal file
Просмотреть файл

@ -0,0 +1,2 @@
.vtfixup [3] int64 fromunmanaged at VTable
.data VTable = int64[3]

Просмотреть файл

@ -49,7 +49,7 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Revision and Build Numbers // You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
[assembly: AssemblyVersion("0.10.0.1")] [assembly: AssemblyVersion("0.11.*")]
// //
// In order to sign your assembly you must specify a key to use. Refer to the // In order to sign your assembly you must specify a key to use. Refer to the

Просмотреть файл

@ -176,7 +176,7 @@ namespace IKVM.Runtime
} }
if(!wrapper.IsAccessibleFrom(context)) if(!wrapper.IsAccessibleFrom(context))
{ {
throw JavaException.IllegalAccessError("Try to access class " + wrapper.Name + " from class " + clazz); throw JavaException.IllegalAccessError("Try to access class " + wrapper.Name + " from class " + context.Name);
} }
wrapper.Finish(); wrapper.Finish();
return wrapper; return wrapper;
@ -262,7 +262,7 @@ namespace IKVM.Runtime
public static object DynamicInvokevirtual(object obj, RuntimeTypeHandle type, string clazz, string name, string sig, object[] args) public static object DynamicInvokevirtual(object obj, RuntimeTypeHandle type, string clazz, string name, string sig, object[] args)
{ {
Profiler.Count("DynamicInvokevirtual"); Profiler.Count("DynamicInvokevirtual");
return GetMethodWrapper(ClassLoaderWrapper.GetWrapperFromType(obj.GetType()), type, clazz, name, sig, false).Invoke(obj, args, true); return GetMethodWrapper(ClassLoaderWrapper.GetWrapperFromType(obj.GetType()), type, clazz, name, sig, false).Invoke(obj, args, false);
} }
[DebuggerStepThroughAttribute] [DebuggerStepThroughAttribute]

Просмотреть файл

@ -1117,7 +1117,19 @@ sealed class ClassFile
field = wrapper.GetFieldWrapper(Name, Signature); field = wrapper.GetFieldWrapper(Name, Signature);
if(field != null) if(field != null)
{ {
field.Link(); bool ok = false;
try
{
field.Link();
ok = true;
}
finally
{
if(!ok)
{
fieldTypeWrapper = null;
}
}
} }
} }
} }
@ -1569,7 +1581,7 @@ sealed class ClassFile
constantValue = (short)classFile.GetConstantPoolConstantInteger(index); constantValue = (short)classFile.GetConstantPoolConstantInteger(index);
break; break;
case "B": case "B":
constantValue = (sbyte)classFile.GetConstantPoolConstantInteger(index); constantValue = (byte)classFile.GetConstantPoolConstantInteger(index);
break; break;
case "C": case "C":
constantValue = (char)classFile.GetConstantPoolConstantInteger(index); constantValue = (char)classFile.GetConstantPoolConstantInteger(index);

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2002, 2003, 2004 Jeroen Frijters Copyright (C) 2002, 2003, 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -504,8 +504,10 @@ class ClassLoaderWrapper
// for .NET to handle. // for .NET to handle.
private TypeWrapper CreateArrayType(string name, TypeWrapper elementTypeWrapper, int dims) private TypeWrapper CreateArrayType(string name, TypeWrapper elementTypeWrapper, int dims)
{ {
Debug.Assert(new String('[', dims) + elementTypeWrapper.SigName == name);
Debug.Assert(!elementTypeWrapper.IsUnloadable && !elementTypeWrapper.IsVerifierType && !elementTypeWrapper.IsArray);
Debug.Assert(dims >= 1);
Type elementType = elementTypeWrapper.TypeAsArrayType; Type elementType = elementTypeWrapper.TypeAsArrayType;
Debug.Assert(!elementType.IsArray);
TypeWrapper wrapper; TypeWrapper wrapper;
lock(types.SyncRoot) lock(types.SyncRoot)
{ {
@ -809,7 +811,7 @@ class ClassLoaderWrapper
Type[] types = new Type[wrappers.Length]; Type[] types = new Type[wrappers.Length];
for(int i = 0; i < wrappers.Length; i++) for(int i = 0; i < wrappers.Length; i++)
{ {
types[i] = wrappers[i].TypeAsParameterType; types[i] = wrappers[i].TypeAsSignatureType;
} }
return types; return types;
} }
@ -986,11 +988,6 @@ class ClassLoaderWrapper
rank++; rank++;
elem = elem.GetElementType(); elem = elem.GetElementType();
} }
// HACK BYTE[]
//if(elem == typeof(byte))
//{
// elem = typeof(sbyte);
//}
wrapper = GetWrapperFromType(elem); wrapper = GetWrapperFromType(elem);
return wrapper.MakeArrayType(rank); return wrapper.MakeArrayType(rank);
} }

Просмотреть файл

@ -79,13 +79,19 @@ namespace IKVM.Runtime
public unsafe sealed class JNI public unsafe sealed class JNI
{ {
internal static bool jvmCreated; internal static bool jvmCreated;
internal static bool jvmDestroyed;
internal const string METHOD_PTR_FIELD_PREFIX = "__<jniptr/"; internal const string METHOD_PTR_FIELD_PREFIX = "__<jniptr/";
internal static bool IsSupportedJniVersion(jint version)
{
return version == JNIEnv.JNI_VERSION_1_1 || version == JNIEnv.JNI_VERSION_1_2 || version == JNIEnv.JNI_VERSION_1_4;
}
public static int CreateJavaVM(void* ppvm, void* ppenv, void* args) public static int CreateJavaVM(void* ppvm, void* ppenv, void* args)
{ {
JavaVMInitArgs* pInitArgs = (JavaVMInitArgs*)args; JavaVMInitArgs* pInitArgs = (JavaVMInitArgs*)args;
// we don't support the JDK 1.1 JavaVMInitArgs // we don't support the JDK 1.1 JavaVMInitArgs
if(pInitArgs->version != JNIEnv.JNI_VERSION_1_2) if(!IsSupportedJniVersion(pInitArgs->version) || pInitArgs->version == JNIEnv.JNI_VERSION_1_1)
{ {
return JNIEnv.JNI_EVERSION; return JNIEnv.JNI_EVERSION;
} }
@ -377,43 +383,11 @@ namespace IKVM.Runtime
[DllImport("ikvm-native")] [DllImport("ikvm-native")]
internal unsafe static extern void* ikvm_MarshalDelegate(Delegate d); internal unsafe static extern void* ikvm_MarshalDelegate(Delegate d);
private static MethodBase FindCaller()
{
StackTrace st = new StackTrace();
for(int i = 0; i < st.FrameCount; i++)
{
StackFrame frame = st.GetFrame(i);
Type type = frame.GetMethod().DeclaringType;
if(type != null && type.Assembly != typeof(JniHelper).Assembly)
{
// TODO we need a more robust algorithm to find the "caller" (note that in addition to native methods,
// System.loadLibrary can also trigger executing native code)
ClassLoaderWrapper loader = ClassLoaderWrapper.GetWrapperFromType(type).GetClassLoader();
if(loader.GetJavaClassLoader() != null)
{
return frame.GetMethod();
}
}
}
return null;
}
private static ArrayList nativeLibraries = new ArrayList(); private static ArrayList nativeLibraries = new ArrayList();
internal static readonly object JniLock = new object(); internal static readonly object JniLock = new object();
internal unsafe static int LoadLibrary(string filename) internal unsafe static int LoadLibrary(string filename, ClassLoaderWrapper loader)
{ {
MethodBase m = FindCaller();
ClassLoaderWrapper loader;
if(m != null)
{
loader = ClassLoaderWrapper.GetWrapperFromType(m.DeclaringType).GetClassLoader();
}
else
{
loader = ClassLoaderWrapper.GetBootstrapClassLoader();
m = MethodBase.GetCurrentMethod();
}
lock(JniLock) lock(JniLock)
{ {
IntPtr p = ikvm_LoadLibrary(filename); IntPtr p = ikvm_LoadLibrary(filename);
@ -444,7 +418,7 @@ namespace IKVM.Runtime
ClassLoaderWrapper prevLoader = f.Enter(loader); ClassLoaderWrapper prevLoader = f.Enter(loader);
int version = ikvm_CallOnLoad(onload, JavaVM.pJavaVM, null); int version = ikvm_CallOnLoad(onload, JavaVM.pJavaVM, null);
f.Leave(prevLoader); f.Leave(prevLoader);
if(!JavaVM.IsSupportedJniVersion(version)) if(!JNI.IsSupportedJniVersion(version))
{ {
throw JavaException.UnsatisfiedLinkError("Unsupported JNI version 0x{0:X} required by {1}", version, filename); throw JavaException.UnsatisfiedLinkError("Unsupported JNI version 0x{0:X} required by {1}", version, filename);
} }
@ -922,8 +896,13 @@ namespace IKVM.Runtime
internal static jint DestroyJavaVM(JavaVM* pJVM) internal static jint DestroyJavaVM(JavaVM* pJVM)
{ {
if(JNI.jvmDestroyed)
{
return JNIEnv.JNI_ERR;
}
JNI.jvmDestroyed = true;
JVM.Library.jniWaitUntilLastThread(); JVM.Library.jniWaitUntilLastThread();
return JNIEnv.JNI_ERR; return JNIEnv.JNI_OK;
} }
internal static jint AttachCurrentThread(JavaVM* pJVM, void **penv, void *args) internal static jint AttachCurrentThread(JavaVM* pJVM, void **penv, void *args)
@ -935,7 +914,7 @@ namespace IKVM.Runtime
{ {
if(pAttachArgs != null) if(pAttachArgs != null)
{ {
if(pAttachArgs->version != JNIEnv.JNI_VERSION_1_2) if(!JNI.IsSupportedJniVersion(pAttachArgs->version) || pAttachArgs->version == JNIEnv.JNI_VERSION_1_1)
{ {
*penv = null; *penv = null;
return JNIEnv.JNI_EVERSION; return JNIEnv.JNI_EVERSION;
@ -950,22 +929,27 @@ namespace IKVM.Runtime
// NOTE if we're here, it is *very* likely that the thread was created by native code and not by managed code, // NOTE if we're here, it is *very* likely that the thread was created by native code and not by managed code,
// but it's not impossible that the thread started life as a managed thread and if it did the changes to the // but it's not impossible that the thread started life as a managed thread and if it did the changes to the
// thread we're making are somewhat dubious. // thread we're making are somewhat dubious.
System.Threading.Thread.CurrentThread.IsBackground = asDaemon;
if(pAttachArgs != null) if(pAttachArgs != null)
{ {
if(pAttachArgs->name != null && System.Threading.Thread.CurrentThread.Name == null) if(pAttachArgs->name != null && System.Threading.Thread.CurrentThread.Name == null)
{ {
System.Threading.Thread.CurrentThread.Name = new String(pAttachArgs->name); try
{
System.Threading.Thread.CurrentThread.Name = new String(pAttachArgs->name);
}
catch(InvalidOperationException)
{
// someone beat us to it...
}
} }
// NOTE we're calling UnwrapRef on a null reference, but that's OK because group is a global reference // NOTE we're calling UnwrapRef on a null reference, but that's OK because group is a global reference
object threadGroup = p->UnwrapRef(pAttachArgs->group); object threadGroup = p->UnwrapRef(pAttachArgs->group);
if(threadGroup != null) if(threadGroup != null)
{ {
// TODO instead of using a thread data slot to communicate the thread group, we should probably use JVM.Library.setThreadGroup(threadGroup);
// another mechanism, this is probably a security issue.
System.Threading.Thread.SetData(System.Threading.Thread.GetNamedDataSlot("ikvm-thread-group"), threadGroup);
} }
} }
System.Threading.Thread.CurrentThread.IsBackground = asDaemon;
*penv = JNIEnv.CreateJNIEnv(); *penv = JNIEnv.CreateJNIEnv();
return JNIEnv.JNI_OK; return JNIEnv.JNI_OK;
} }
@ -974,7 +958,8 @@ namespace IKVM.Runtime
{ {
if(TlsHack.pJNIEnv == null) if(TlsHack.pJNIEnv == null)
{ {
return JNIEnv.JNI_EDETACHED; // the JDK allows detaching from an already detached thread
return JNIEnv.JNI_OK;
} }
// TODO if we set Thread.IsBackground to false when we attached, now might be a good time to set it back to true. // TODO if we set Thread.IsBackground to false when we attached, now might be a good time to set it back to true.
JNIEnv.FreeJNIEnv(); JNIEnv.FreeJNIEnv();
@ -982,14 +967,9 @@ namespace IKVM.Runtime
return JNIEnv.JNI_OK; return JNIEnv.JNI_OK;
} }
internal static bool IsSupportedJniVersion(jint version)
{
return version == JNIEnv.JNI_VERSION_1_1 || version == JNIEnv.JNI_VERSION_1_2 || version == JNIEnv.JNI_VERSION_1_4;
}
internal static jint GetEnv(JavaVM* pJVM, void **penv, jint version) internal static jint GetEnv(JavaVM* pJVM, void **penv, jint version)
{ {
if(IsSupportedJniVersion(version)) if(JNI.IsSupportedJniVersion(version))
{ {
JNIEnv* p = TlsHack.pJNIEnv; JNIEnv* p = TlsHack.pJNIEnv;
if(p != null) if(p != null)
@ -1013,6 +993,8 @@ namespace IKVM.Runtime
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
unsafe struct JNIEnv unsafe struct JNIEnv
{ {
// NOTE LOCAL_REF_BUCKET_SIZE must be at least 512 to allow all method arguments to fit
// in a single slot, because Frame.MakeLocalRef() doesn't support spilling into a new bucket
internal const int LOCAL_REF_SHIFT = 10; internal const int LOCAL_REF_SHIFT = 10;
internal const int LOCAL_REF_BUCKET_SIZE = (1 << LOCAL_REF_SHIFT); internal const int LOCAL_REF_BUCKET_SIZE = (1 << LOCAL_REF_SHIFT);
internal const int LOCAL_REF_MASK = (LOCAL_REF_BUCKET_SIZE - 1); internal const int LOCAL_REF_MASK = (LOCAL_REF_BUCKET_SIZE - 1);
@ -1255,23 +1237,38 @@ namespace IKVM.Runtime
return ClassLoaderWrapper.GetSystemClassLoader(); return ClassLoaderWrapper.GetSystemClassLoader();
} }
internal static jclass FindClass(JNIEnv* pEnv, byte* name) internal static jclass FindClass(JNIEnv* pEnv, byte* pszName)
{ {
try try
{ {
TypeWrapper wrapper = FindNativeMethodClassLoader(pEnv).LoadClassByDottedName(new String((sbyte*)name).Replace('/', '.')); string name = new String((sbyte*)pszName);
// don't allow dotted names!
if(name.IndexOf('.') >= 0)
{
SetPendingException(pEnv, JavaException.NoClassDefFoundError(name));
return IntPtr.Zero;
}
// spec doesn't say it, but Sun allows signature format class names (but not for primitives)
if(name.StartsWith("L") && name.EndsWith(";"))
{
name = name.Substring(1, name.Length - 2);
}
TypeWrapper wrapper = FindNativeMethodClassLoader(pEnv).LoadClassByDottedName(name.Replace('/', '.'));
wrapper.Finish(); wrapper.Finish();
// spec doesn't say it, but Sun runs the static initializer // spec doesn't say it, but Sun runs the static initializer
wrapper.RunClassInit(); wrapper.RunClassInit();
return pEnv->MakeLocalRef(wrapper.ClassObject); return pEnv->MakeLocalRef(wrapper.ClassObject);
} }
catch(RetargetableJavaException x)
{
SetPendingException(pEnv, x.ToJava());
return IntPtr.Zero;
}
catch(Exception x) catch(Exception x)
{ {
if(x is RetargetableJavaException)
{
x = ((RetargetableJavaException)x).ToJava();
}
if(ClassLoaderWrapper.LoadClassCritical("java.lang.ClassNotFoundException").TypeAsTBD.IsInstanceOfType(x))
{
x = JavaException.NoClassDefFoundError(x.Message);
}
SetPendingException(pEnv, x); SetPendingException(pEnv, x);
return IntPtr.Zero; return IntPtr.Zero;
} }
@ -1415,8 +1412,15 @@ namespace IKVM.Runtime
localRefs[pEnv->localRefSlot - 1] = null; localRefs[pEnv->localRefSlot - 1] = null;
if(localRefs[pEnv->localRefSlot] == null) if(localRefs[pEnv->localRefSlot] == null)
{ {
// we can't use capacity, because the array length must be a power of two // we can't use capacity directly, because the array length must be a power of two
localRefs[pEnv->localRefSlot] = new object[LOCAL_REF_BUCKET_SIZE]; // and it can't be bigger than LOCAL_REF_BUCKET_SIZE
int r = 1;
capacity = Math.Min(capacity, LOCAL_REF_BUCKET_SIZE);
while(r < capacity)
{
r *= 2;
}
localRefs[pEnv->localRefSlot] = new object[r];
} }
return JNI_OK; return JNI_OK;
} }
@ -1600,7 +1604,7 @@ namespace IKVM.Runtime
} }
catch(Exception x) catch(Exception x)
{ {
if(x.GetType() == ClassLoaderWrapper.LoadClassCritical("java.lang.reflect.InvocationTargetException").TypeAsExceptionType) if(ClassLoaderWrapper.LoadClassCritical("java.lang.reflect.InvocationTargetException").TypeAsExceptionType.IsInstanceOfType(x))
{ {
x = x.InnerException; x = x.InnerException;
} }
@ -1621,6 +1625,8 @@ namespace IKVM.Runtime
internal static jboolean IsInstanceOf(JNIEnv* pEnv, jobject obj, jclass clazz) internal static jboolean IsInstanceOf(JNIEnv* pEnv, jobject obj, jclass clazz)
{ {
// NOTE if clazz is an interface, this is still the right thing to do
// (i.e. if the object implements the interface, we return true)
object objClass = IKVM.Runtime.Util.GetClassFromObject(pEnv->UnwrapRef(obj)); object objClass = IKVM.Runtime.Util.GetClassFromObject(pEnv->UnwrapRef(obj));
TypeWrapper w1 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)); TypeWrapper w1 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
TypeWrapper w2 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(objClass); TypeWrapper w2 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(objClass);
@ -1680,7 +1686,7 @@ namespace IKVM.Runtime
object o = InvokeHelper(pEnv, obj, methodID, args, false); object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null) if(o != null)
{ {
return (jbyte)(sbyte)o; return (jbyte)(byte)o;
} }
return 0; return 0;
} }
@ -1770,7 +1776,7 @@ namespace IKVM.Runtime
object o = InvokeHelper(pEnv, obj, methodID, args, true); object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null) if(o != null)
{ {
return (jbyte)(sbyte)o; return (jbyte)(byte)o;
} }
return 0; return 0;
} }
@ -1851,7 +1857,6 @@ namespace IKVM.Runtime
{ {
if(fw.IsStatic == isstatic) if(fw.IsStatic == isstatic)
{ {
// TODO fw.Link()
return fw.Cookie; return fw.Cookie;
} }
} }
@ -1911,7 +1916,7 @@ namespace IKVM.Runtime
internal static jbyte GetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jbyte GetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{ {
return (jbyte)(sbyte)GetFieldValue(fieldID, pEnv->UnwrapRef(obj)); return (jbyte)(byte)GetFieldValue(fieldID, pEnv->UnwrapRef(obj));
} }
internal static jchar GetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID) internal static jchar GetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
@ -1956,7 +1961,7 @@ namespace IKVM.Runtime
internal static void SetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val) internal static void SetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val)
{ {
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (sbyte)val); SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (byte)val);
} }
internal static void SetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val) internal static void SetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val)
@ -2014,7 +2019,7 @@ namespace IKVM.Runtime
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false); object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null) if(o != null)
{ {
return (jbyte)(sbyte)o; return (jbyte)(byte)o;
} }
return 0; return 0;
} }
@ -2101,7 +2106,7 @@ namespace IKVM.Runtime
internal static jbyte GetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jbyte GetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{ {
return (jbyte)(sbyte)GetFieldValue(fieldID, null); return (jbyte)(byte)GetFieldValue(fieldID, null);
} }
internal static jchar GetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID) internal static jchar GetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
@ -2146,7 +2151,7 @@ namespace IKVM.Runtime
internal static void SetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte val) internal static void SetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte val)
{ {
SetFieldValue(fieldID, null, (sbyte)val); SetFieldValue(fieldID, null, (byte)val);
} }
internal static void SetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar val) internal static void SetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar val)
@ -2328,7 +2333,7 @@ namespace IKVM.Runtime
{ {
try try
{ {
return pEnv->MakeLocalRef(new sbyte[len]); return pEnv->MakeLocalRef(new byte[len]);
} }
catch(Exception x) catch(Exception x)
{ {
@ -2432,7 +2437,7 @@ namespace IKVM.Runtime
internal static jbyte* GetByteArrayElements(JNIEnv* pEnv, jbyteArray array, jboolean* isCopy) internal static jbyte* GetByteArrayElements(JNIEnv* pEnv, jbyteArray array, jboolean* isCopy)
{ {
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array); byte[] b = (byte[])pEnv->UnwrapRef(array);
jbyte* p = (jbyte*)(void*)JniMem.Alloc(b.Length * 1); jbyte* p = (jbyte*)(void*)JniMem.Alloc(b.Length * 1);
for(int i = 0; i < b.Length; i++) for(int i = 0; i < b.Length; i++)
{ {
@ -2537,10 +2542,10 @@ namespace IKVM.Runtime
{ {
if(mode == 0 || mode == JNI_COMMIT) if(mode == 0 || mode == JNI_COMMIT)
{ {
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array); byte[] b = (byte[])pEnv->UnwrapRef(array);
for(int i = 0; i < b.Length; i++) for(int i = 0; i < b.Length; i++)
{ {
b[i] = (sbyte)elems[i]; b[i] = (byte)elems[i];
} }
} }
if(mode == 0 || mode == JNI_ABORT) if(mode == 0 || mode == JNI_ABORT)
@ -2648,8 +2653,8 @@ namespace IKVM.Runtime
{ {
try try
{ {
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array); byte[] b = (byte[])pEnv->UnwrapRef(array);
sbyte* p = (sbyte*)(void*)buf; byte* p = (byte*)(void*)buf;
for(int i = 0; i < len; i++) for(int i = 0; i < len; i++)
{ {
*p++ = b[start + i]; *p++ = b[start + i];
@ -2760,8 +2765,8 @@ namespace IKVM.Runtime
{ {
try try
{ {
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array); byte[] b = (byte[])pEnv->UnwrapRef(array);
sbyte* p = (sbyte*)(void*)buf; byte* p = (byte*)(void*)buf;
for(int i = 0; i < len; i++) for(int i = 0; i < len; i++)
{ {
b[start + i] = *p++; b[start + i] = *p++;
@ -3023,19 +3028,19 @@ namespace IKVM.Runtime
private static int GetPrimitiveArrayElementSize(Array ar) private static int GetPrimitiveArrayElementSize(Array ar)
{ {
Type type = ar.GetType().GetElementType(); Type type = ar.GetType().GetElementType();
if(type == typeof(sbyte) || type == typeof(bool)) if(type == PrimitiveTypeWrapper.BYTE.TypeAsArrayType || type == PrimitiveTypeWrapper.BOOLEAN.TypeAsArrayType)
{ {
return 1; return 1;
} }
else if(type == typeof(short) || type == typeof(char)) else if(type == PrimitiveTypeWrapper.SHORT.TypeAsArrayType || type == PrimitiveTypeWrapper.CHAR.TypeAsArrayType)
{ {
return 2; return 2;
} }
else if(type == typeof(int) || type == typeof(float)) else if(type == PrimitiveTypeWrapper.INT.TypeAsArrayType || type == PrimitiveTypeWrapper.FLOAT.TypeAsArrayType)
{ {
return 4; return 4;
} }
else if(type == typeof(long) || type == typeof(double)) else if(type == PrimitiveTypeWrapper.LONG.TypeAsArrayType || type == PrimitiveTypeWrapper.DOUBLE.TypeAsArrayType)
{ {
return 8; return 8;
} }
@ -3049,6 +3054,7 @@ namespace IKVM.Runtime
internal static IntPtr GetPrimitiveArrayCritical(JNIEnv* pEnv, IntPtr array, IntPtr isCopy) internal static IntPtr GetPrimitiveArrayCritical(JNIEnv* pEnv, IntPtr array, IntPtr isCopy)
{ {
Array ar = (Array)pEnv->UnwrapRef(array); Array ar = (Array)pEnv->UnwrapRef(array);
// TODO not 64-bit safe (len can overflow)
int len = ar.Length * GetPrimitiveArrayElementSize(ar); int len = ar.Length * GetPrimitiveArrayElementSize(ar);
GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned); GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned);
try try
@ -3078,6 +3084,7 @@ namespace IKVM.Runtime
if(mode == 0 || mode == JNI_COMMIT) if(mode == 0 || mode == JNI_COMMIT)
{ {
Array ar = (Array)pEnv->UnwrapRef(array); Array ar = (Array)pEnv->UnwrapRef(array);
// TODO not 64-bit safe (len can overflow)
int len = ar.Length * GetPrimitiveArrayElementSize(ar); int len = ar.Length * GetPrimitiveArrayElementSize(ar);
GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned); GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned);
try try
@ -3165,7 +3172,7 @@ namespace IKVM.Runtime
} }
} }
internal static sbyte ExceptionCheck(JNIEnv* pEnv) internal static jboolean ExceptionCheck(JNIEnv* pEnv)
{ {
return pEnv->UnwrapRef(pEnv->pendingException) != null ? JNI_TRUE : JNI_FALSE; return pEnv->UnwrapRef(pEnv->pendingException) != null ? JNI_TRUE : JNI_FALSE;
} }

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2002, 2003, 2004 Jeroen Frijters Copyright (C) 2002, 2003, 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -209,7 +209,7 @@ abstract class MethodWrapper : MemberWrapper
{ {
if(ghostMethod == null) if(ghostMethod == null)
{ {
ghostMethod = DeclaringType.TypeAsParameterType.GetMethod(this.Name, this.GetParametersForDefineMethod()); ghostMethod = DeclaringType.TypeAsSignatureType.GetMethod(this.Name, this.GetParametersForDefineMethod());
if(ghostMethod == null) if(ghostMethod == null)
{ {
throw new InvalidOperationException("Unable to resolve ghost method"); throw new InvalidOperationException("Unable to resolve ghost method");
@ -225,7 +225,7 @@ abstract class MethodWrapper : MemberWrapper
internal override object Invoke(object obj, object[] args, bool nonVirtual) internal override object Invoke(object obj, object[] args, bool nonVirtual)
{ {
object wrapper = Activator.CreateInstance(DeclaringType.TypeAsParameterType); object wrapper = Activator.CreateInstance(DeclaringType.TypeAsSignatureType);
DeclaringType.GhostRefField.SetValue(wrapper, obj); DeclaringType.GhostRefField.SetValue(wrapper, obj);
ResolveGhostMethod(); ResolveGhostMethod();
@ -245,7 +245,7 @@ abstract class MethodWrapper : MemberWrapper
Type[] types = new Type[parameterTypes.Length]; Type[] types = new Type[parameterTypes.Length];
for(int i = 0; i < types.Length; i++) for(int i = 0; i < types.Length; i++)
{ {
types[i] = parameterTypes[i].TypeAsParameterType; types[i] = parameterTypes[i].TypeAsSignatureType;
} }
method = declaringType.TypeAsBaseType.GetMethod(method.Name, types); method = declaringType.TypeAsBaseType.GetMethod(method.Name, types);
} }
@ -383,7 +383,7 @@ abstract class MethodWrapper : MemberWrapper
{ {
get get
{ {
return ReturnType.TypeAsParameterType; return ReturnType.TypeAsSignatureType;
} }
} }
@ -393,7 +393,7 @@ abstract class MethodWrapper : MemberWrapper
Type[] temp = new Type[wrappers.Length]; Type[] temp = new Type[wrappers.Length];
for(int i = 0; i < wrappers.Length; i++) for(int i = 0; i < wrappers.Length; i++)
{ {
temp[i] = wrappers[i].TypeAsParameterType; temp[i] = wrappers[i].TypeAsSignatureType;
} }
return temp; return temp;
} }
@ -600,7 +600,12 @@ abstract class MethodWrapper : MemberWrapper
} }
} }
} }
else if(nonVirtual && !method.IsStatic) else if(nonVirtual &&
method.IsVirtual && // if the method isn't virtual, normal reflection will work
!method.IsFinal && // if the method is final, normal reflection will work
!method.DeclaringType.IsSealed && // if the type is sealed, normal reflection will work
!method.IsAbstract) // if the method is abstract, it doesn't make sense, so we'll do a virtual call
// (Sun does a virtual call for interface methods and crashes for abstract methods)
{ {
Invoker invoker = NonvirtualInvokeHelper.GetInvoker(this); Invoker invoker = NonvirtualInvokeHelper.GetInvoker(this);
try try
@ -683,6 +688,8 @@ abstract class MethodWrapper : MemberWrapper
AssemblyName name = new AssemblyName(); AssemblyName name = new AssemblyName();
name.Name = "NonvirtualInvoker"; name.Name = "NonvirtualInvoker";
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(name, ClassLoaderWrapper.IsSaveDebugImage ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run); AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(name, ClassLoaderWrapper.IsSaveDebugImage ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run);
// the stack walker needs access to this assembly to be able to quickly check for non-virtual invoke frames
IKVM.NativeCode.gnu.classpath.VMStackWalker.nonVirtualInvokeAssembly = ab;
if(ClassLoaderWrapper.IsSaveDebugImage) if(ClassLoaderWrapper.IsSaveDebugImage)
{ {
module = ab.DefineDynamicModule("NonvirtualInvoker", "NonvirtualInvoker.dll"); module = ab.DefineDynamicModule("NonvirtualInvoker", "NonvirtualInvoker.dll");
@ -747,7 +754,10 @@ abstract class MethodWrapper : MemberWrapper
} }
else if(mw.ReturnType.IsGhost) else if(mw.ReturnType.IsGhost)
{ {
mw.ReturnType.EmitConvParameterToStackType(ilgen); LocalBuilder local = ilgen.DeclareLocal(mw.ReturnType.TypeAsSignatureType);
ilgen.Emit(OpCodes.Stloc, local);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldfld, mw.ReturnType.GhostRefField);
} }
else if(mw.ReturnType.IsPrimitive) else if(mw.ReturnType.IsPrimitive)
{ {
@ -780,7 +790,7 @@ abstract class MethodWrapper : MemberWrapper
{ {
if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost) if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost)
{ {
object v = Activator.CreateInstance(argTypes[i].TypeAsParameterType); object v = Activator.CreateInstance(argTypes[i].TypeAsSignatureType);
argTypes[i].GhostRefField.SetValue(v, args[i + 1]); argTypes[i].GhostRefField.SetValue(v, args[i + 1]);
args[i + 1] = v; args[i + 1] = v;
} }
@ -798,7 +808,7 @@ abstract class MethodWrapper : MemberWrapper
{ {
this.args = (object[])args.Clone(); this.args = (object[])args.Clone();
} }
object v = Activator.CreateInstance(argTypes[i].TypeAsParameterType); object v = Activator.CreateInstance(argTypes[i].TypeAsSignatureType);
argTypes[i].GhostRefField.SetValue(v, args[i]); argTypes[i].GhostRefField.SetValue(v, args[i]);
this.args[i] = v; this.args[i] = v;
} }
@ -844,31 +854,11 @@ class SmartMethodWrapper : MethodWrapper
{ {
} }
protected void PostEmit(ILGenerator ilgen)
{
TypeWrapper retType = this.ReturnType;
if(!retType.IsUnloadable)
{
if(retType.IsNonPrimitiveValueType)
{
retType.EmitBox(ilgen);
}
else if(retType.IsGhost)
{
LocalBuilder local = ilgen.DeclareLocal(retType.TypeAsParameterType);
ilgen.Emit(OpCodes.Stloc, local);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldfld, retType.GhostRefField);
}
}
}
internal sealed override void EmitCall(ILGenerator ilgen) internal sealed override void EmitCall(ILGenerator ilgen)
{ {
AssertLinked(); AssertLinked();
PreEmit(ilgen); PreEmit(ilgen);
CallImpl(ilgen); CallImpl(ilgen);
PostEmit(ilgen);
} }
protected virtual void CallImpl(ILGenerator ilgen) protected virtual void CallImpl(ILGenerator ilgen)
@ -883,13 +873,13 @@ class SmartMethodWrapper : MethodWrapper
if(DeclaringType.IsNonPrimitiveValueType) if(DeclaringType.IsNonPrimitiveValueType)
{ {
// callvirt isn't allowed on a value type // callvirt isn't allowed on a value type
// TODO we need to check for a null reference
CallImpl(ilgen); CallImpl(ilgen);
} }
else else
{ {
CallvirtImpl(ilgen); CallvirtImpl(ilgen);
} }
PostEmit(ilgen);
} }
protected virtual void CallvirtImpl(ILGenerator ilgen) protected virtual void CallvirtImpl(ILGenerator ilgen)
@ -1282,91 +1272,32 @@ sealed class SimpleFieldWrapper : FieldWrapper
protected override void EmitGetImpl(ILGenerator ilgen) protected override void EmitGetImpl(ILGenerator ilgen)
{ {
if(FieldTypeWrapper.IsGhost) if(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
{ {
FieldInfo fi = GetField(); ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
if(fi.IsStatic)
{
ilgen.Emit(OpCodes.Ldsflda, fi);
}
else
{
if(DeclaringType.IsNonPrimitiveValueType)
{
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
}
ilgen.Emit(OpCodes.Ldflda, fi);
}
if(IsVolatile)
{
ilgen.Emit(OpCodes.Volatile);
}
ilgen.Emit(OpCodes.Ldfld, FieldTypeWrapper.GhostRefField);
} }
else if(IsVolatile)
{ {
if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) ilgen.Emit(OpCodes.Volatile);
{
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
}
if(IsVolatile)
{
ilgen.Emit(OpCodes.Volatile);
}
ilgen.Emit(IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, GetField());
if(!FieldTypeWrapper.IsUnloadable && FieldTypeWrapper.IsNonPrimitiveValueType)
{
FieldTypeWrapper.EmitBox(ilgen);
}
} }
ilgen.Emit(IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, GetField());
} }
protected override void EmitSetImpl(ILGenerator ilgen) protected override void EmitSetImpl(ILGenerator ilgen)
{ {
if(FieldTypeWrapper.IsGhost) FieldInfo fi = GetField();
if(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
{ {
FieldInfo fi = GetField(); LocalBuilder temp = ilgen.DeclareLocal(fi.FieldType);
LocalBuilder temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
ilgen.Emit(OpCodes.Stloc, temp); ilgen.Emit(OpCodes.Stloc, temp);
if(fi.IsStatic) ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
{
ilgen.Emit(OpCodes.Ldsflda, fi);
}
else
{
if(DeclaringType.IsNonPrimitiveValueType)
{
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
}
ilgen.Emit(OpCodes.Ldflda, fi);
}
ilgen.Emit(OpCodes.Ldloc, temp); ilgen.Emit(OpCodes.Ldloc, temp);
if(IsVolatile)
{
ilgen.Emit(OpCodes.Volatile);
}
ilgen.Emit(OpCodes.Stfld, FieldTypeWrapper.GhostRefField);
} }
else if(IsVolatile)
{ {
if(!IsStatic && DeclaringType.IsNonPrimitiveValueType) ilgen.Emit(OpCodes.Volatile);
{
FieldInfo fi = GetField();
LocalBuilder temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
ilgen.Emit(OpCodes.Stloc, temp);
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
ilgen.Emit(OpCodes.Ldloc, temp);
}
if(!FieldTypeWrapper.IsUnloadable && FieldTypeWrapper.IsNonPrimitiveValueType)
{
FieldTypeWrapper.EmitUnbox(ilgen);
}
if(IsVolatile)
{
ilgen.Emit(OpCodes.Volatile);
}
ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, GetField());
} }
ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi);
} }
} }
@ -1381,7 +1312,7 @@ sealed class VolatileLongDoubleFieldWrapper : FieldWrapper
: base(declaringType, fieldType, name, sig, modifiers, fi) : base(declaringType, fieldType, name, sig, modifiers, fi)
{ {
Debug.Assert(IsVolatile); Debug.Assert(IsVolatile);
Debug.Assert(fieldType == PrimitiveTypeWrapper.DOUBLE || fieldType == PrimitiveTypeWrapper.LONG); Debug.Assert(sig == "J" || sig == "D");
} }
protected override void EmitGetImpl(ILGenerator ilgen) protected override void EmitGetImpl(ILGenerator ilgen)
@ -1460,88 +1391,30 @@ sealed class GetterFieldWrapper : FieldWrapper
protected override void EmitGetImpl(ILGenerator ilgen) protected override void EmitGetImpl(ILGenerator ilgen)
{ {
if(IsStatic) if(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
{ {
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
ilgen.Emit(OpCodes.Call, getter); ilgen.Emit(OpCodes.Call, getter);
} }
else else
{ {
if(DeclaringType.IsNonPrimitiveValueType) // NOTE we look at the static-ness of the getter method and not our own,
{ // because for instance fields we can still have a static getter method
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD); ilgen.Emit(getter.IsStatic ? OpCodes.Call : OpCodes.Callvirt, getter);
ilgen.Emit(OpCodes.Call, getter);
}
else
{
ilgen.Emit(getter.IsStatic ? OpCodes.Call : OpCodes.Callvirt, getter);
}
}
if(FieldTypeWrapper.IsUnloadable)
{
// no need to do anything
}
else if(FieldTypeWrapper.IsGhost)
{
LocalBuilder temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsFieldType);
ilgen.Emit(OpCodes.Stloc, temp);
ilgen.Emit(OpCodes.Ldloca, temp);
ilgen.Emit(OpCodes.Ldfld, FieldTypeWrapper.GhostRefField);
}
else if(FieldTypeWrapper.IsNonPrimitiveValueType)
{
FieldTypeWrapper.EmitBox(ilgen);
} }
} }
protected override void EmitSetImpl(ILGenerator ilgen) protected override void EmitSetImpl(ILGenerator ilgen)
{ {
FieldInfo fi = GetField(); FieldInfo fi = GetField();
if(FieldTypeWrapper.IsUnloadable) if(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
{ {
LocalBuilder temp = ilgen.DeclareLocal(typeof(object)); LocalBuilder temp = ilgen.DeclareLocal(fi.FieldType);
ilgen.Emit(OpCodes.Stloc, temp); ilgen.Emit(OpCodes.Stloc, temp);
if(DeclaringType.IsNonPrimitiveValueType) ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
{
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
}
ilgen.Emit(OpCodes.Ldloc, temp); ilgen.Emit(OpCodes.Ldloc, temp);
ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi);
}
else
{
LocalBuilder temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
ilgen.Emit(OpCodes.Stloc, temp);
if(FieldTypeWrapper.IsGhost)
{
if(fi.IsStatic)
{
ilgen.Emit(OpCodes.Ldsflda, fi);
}
else
{
if(DeclaringType.IsNonPrimitiveValueType)
{
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
}
ilgen.Emit(OpCodes.Ldflda, fi);
}
ilgen.Emit(OpCodes.Ldloc, temp);
ilgen.Emit(OpCodes.Stfld, FieldTypeWrapper.GhostRefField);
}
else
{
if(DeclaringType.IsNonPrimitiveValueType)
{
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
}
ilgen.Emit(OpCodes.Ldloc, temp);
if(FieldTypeWrapper.IsNonPrimitiveValueType)
{
FieldTypeWrapper.EmitUnbox(ilgen);
}
ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi);
}
} }
ilgen.Emit(IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, fi);
} }
} }
@ -1569,6 +1442,8 @@ sealed class ConstantFieldWrapper : FieldWrapper
} }
else if(constant is int || else if(constant is int ||
constant is short || constant is short ||
constant is ushort ||
constant is byte ||
constant is sbyte || constant is sbyte ||
constant is char || constant is char ||
constant is bool) constant is bool)
@ -1591,25 +1466,13 @@ sealed class ConstantFieldWrapper : FieldWrapper
{ {
ilgen.Emit(OpCodes.Ldc_I8, (long)constant); ilgen.Emit(OpCodes.Ldc_I8, (long)constant);
} }
else if(constant is byte)
{
ilgen.Emit(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null));
ilgen.Emit(OpCodes.Box, typeof(byte));
}
else if(constant is ushort)
{
ilgen.Emit(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null));
ilgen.Emit(OpCodes.Box, typeof(ushort));
}
else if(constant is uint) else if(constant is uint)
{ {
ilgen.Emit(OpCodes.Ldc_I4, unchecked((int)((IConvertible)constant).ToUInt32(null))); ilgen.Emit(OpCodes.Ldc_I4, unchecked((int)((IConvertible)constant).ToUInt32(null)));
ilgen.Emit(OpCodes.Box, typeof(uint));
} }
else if(constant is ulong) else if(constant is ulong)
{ {
ilgen.Emit(OpCodes.Ldc_I8, unchecked((long)(ulong)constant)); ilgen.Emit(OpCodes.Ldc_I8, unchecked((long)(ulong)constant));
ilgen.Emit(OpCodes.Box, typeof(ulong));
} }
else if(constant is Enum) else if(constant is Enum)
{ {
@ -1617,12 +1480,10 @@ sealed class ConstantFieldWrapper : FieldWrapper
if(val is long) if(val is long)
{ {
ilgen.Emit(OpCodes.Ldc_I8, (long)constant); ilgen.Emit(OpCodes.Ldc_I8, (long)constant);
ilgen.Emit(OpCodes.Box, constant.GetType());
} }
else else
{ {
ilgen.Emit(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null)); ilgen.Emit(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null));
ilgen.Emit(OpCodes.Box, constant.GetType());
} }
} }
else else
@ -1635,6 +1496,7 @@ sealed class ConstantFieldWrapper : FieldWrapper
{ {
// when constant static final fields are updated, the JIT normally doesn't see that (because the // when constant static final fields are updated, the JIT normally doesn't see that (because the
// constant value is inlined), so we emulate that behavior by emitting a Pop // constant value is inlined), so we emulate that behavior by emitting a Pop
// TODO can we have a constant instance field?
ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Pop);
} }

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2002, 2003, 2004 Jeroen Frijters Copyright (C) 2002, 2003, 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -472,7 +472,7 @@ abstract class TypeWrapper
this.name = name; this.name = name;
this.baseWrapper = baseWrapper; this.baseWrapper = baseWrapper;
this.classLoader = classLoader; this.classLoader = classLoader;
if(JVM.IsStaticCompiler) if(IsUnloadable || IsVerifierType || JVM.IsStaticCompiler)
{ {
this.classObject = null; this.classObject = null;
} }
@ -486,7 +486,7 @@ abstract class TypeWrapper
{ {
get get
{ {
Debug.Assert(!IsUnloadable); Debug.Assert(!IsUnloadable && !IsVerifierType);
return classObject; return classObject;
} }
} }
@ -902,15 +902,7 @@ abstract class TypeWrapper
} }
} }
internal Type TypeAsFieldType internal Type TypeAsSignatureType
{
get
{
return TypeAsParameterType;
}
}
internal Type TypeAsParameterType
{ {
get get
{ {
@ -991,13 +983,7 @@ abstract class TypeWrapper
} }
return Type.GetType(type, true); return Type.GetType(type, true);
} }
Type t = TypeAsTBD; return TypeAsTBD;
// HACK BYTE[]
//if(t == typeof(sbyte))
//{
// return typeof(byte);
//}
return t;
} }
} }
@ -1337,9 +1323,31 @@ abstract class TypeWrapper
ilgen.Emit(OpCodes.Box, this.TypeAsTBD); ilgen.Emit(OpCodes.Box, this.TypeAsTBD);
} }
// NOTE sourceType is optional and only used for special types (e.g. interfaces), internal void EmitConvSignatureTypeToStackType(ILGenerator ilgen)
{
if(IsUnloadable)
{
}
else if(this == PrimitiveTypeWrapper.BYTE)
{
ilgen.Emit(OpCodes.Conv_I1);
}
else if(IsNonPrimitiveValueType)
{
EmitBox(ilgen);
}
else if(IsGhost)
{
LocalBuilder local = ilgen.DeclareLocal(TypeAsSignatureType);
ilgen.Emit(OpCodes.Stloc, local);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldfld, GhostRefField);
}
}
// NOTE sourceType is optional and only used for interfaces,
// it is *not* used to automatically downcast // it is *not* used to automatically downcast
internal void EmitConvStackToParameterType(ILGenerator ilgen, TypeWrapper sourceType) internal void EmitConvStackTypeToSignatureType(ILGenerator ilgen, TypeWrapper sourceType)
{ {
if(!IsUnloadable) if(!IsUnloadable)
{ {
@ -1347,12 +1355,12 @@ abstract class TypeWrapper
{ {
LocalBuilder local1 = ilgen.DeclareLocal(TypeAsLocalOrStackType); LocalBuilder local1 = ilgen.DeclareLocal(TypeAsLocalOrStackType);
ilgen.Emit(OpCodes.Stloc, local1); ilgen.Emit(OpCodes.Stloc, local1);
LocalBuilder local2 = ilgen.DeclareLocal(TypeAsParameterType); LocalBuilder local2 = ilgen.DeclareLocal(TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local2); ilgen.Emit(OpCodes.Ldloca, local2);
ilgen.Emit(OpCodes.Ldloc, local1); ilgen.Emit(OpCodes.Ldloc, local1);
ilgen.Emit(OpCodes.Stfld, GhostRefField); ilgen.Emit(OpCodes.Stfld, GhostRefField);
ilgen.Emit(OpCodes.Ldloca, local2); ilgen.Emit(OpCodes.Ldloca, local2);
ilgen.Emit(OpCodes.Ldobj, TypeAsParameterType); ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType);
} }
// because of the way interface merging works, any reference is valid // because of the way interface merging works, any reference is valid
// for any interface reference // for any interface reference
@ -1367,25 +1375,6 @@ abstract class TypeWrapper
} }
} }
internal void EmitConvParameterToStackType(ILGenerator ilgen)
{
if(IsUnloadable)
{
// nothing to do
}
else if(IsNonPrimitiveValueType)
{
EmitBox(ilgen);
}
else if(IsGhost)
{
LocalBuilder local = ilgen.DeclareLocal(TypeAsParameterType);
ilgen.Emit(OpCodes.Stloc, local);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldfld, GhostRefField);
}
}
internal virtual void EmitCheckcast(TypeWrapper context, ILGenerator ilgen) internal virtual void EmitCheckcast(TypeWrapper context, ILGenerator ilgen)
{ {
if(IsGhost) if(IsGhost)
@ -1599,7 +1588,7 @@ class UnloadableTypeWrapper : TypeWrapper
class PrimitiveTypeWrapper : TypeWrapper class PrimitiveTypeWrapper : TypeWrapper
{ {
internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper(typeof(sbyte), "B"); internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper(typeof(byte), "B");
internal static readonly PrimitiveTypeWrapper CHAR = new PrimitiveTypeWrapper(typeof(char), "C"); internal static readonly PrimitiveTypeWrapper CHAR = new PrimitiveTypeWrapper(typeof(char), "C");
internal static readonly PrimitiveTypeWrapper DOUBLE = new PrimitiveTypeWrapper(typeof(double), "D"); internal static readonly PrimitiveTypeWrapper DOUBLE = new PrimitiveTypeWrapper(typeof(double), "D");
internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper(typeof(float), "F"); internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper(typeof(float), "F");
@ -1675,6 +1664,11 @@ class PrimitiveTypeWrapper : TypeWrapper
internal override void Finish(bool forDebugSave) internal override void Finish(bool forDebugSave)
{ {
} }
public override string ToString()
{
return "PrimitiveTypeWrapper[" + sigName + "]";
}
} }
class BakedTypeCleanupHack class BakedTypeCleanupHack
@ -2278,6 +2272,8 @@ sealed class DynamicTypeWrapper : TypeWrapper
{ {
if(wrapper.IsGhost) if(wrapper.IsGhost)
{ {
// TODO this is low priority, since the current Java class library doesn't define any ghost interfaces
// as inner classes
throw new NotImplementedException(); throw new NotImplementedException();
} }
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced // LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
@ -2473,11 +2469,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
{ {
for(int i = 0; i < caller.Length; i++) for(int i = 0; i < caller.Length; i++)
{ {
if(caller[i].TypeAsParameterType == typeof(sbyte[]) && callee[i].TypeAsParameterType == typeof(byte[])) if(!caller[i].IsAssignableTo(callee[i]))
{
// special case for byte array cheating...
}
else if(!caller[i].IsAssignableTo(callee[i]))
{ {
return false; return false;
} }
@ -2629,7 +2621,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
ClassFile.Field fld = classFile.Fields[GetFieldIndex(fw)]; ClassFile.Field fld = classFile.Fields[GetFieldIndex(fw)];
string fieldName = fld.Name; string fieldName = fld.Name;
TypeWrapper typeWrapper = fw.FieldTypeWrapper; TypeWrapper typeWrapper = fw.FieldTypeWrapper;
Type type = typeWrapper.TypeAsFieldType; Type type = typeWrapper.TypeAsSignatureType;
bool setNameSig = typeWrapper.IsUnloadable || typeWrapper.IsGhostArray; bool setNameSig = typeWrapper.IsUnloadable || typeWrapper.IsGhostArray;
if(setNameSig) if(setNameSig)
{ {
@ -2905,15 +2897,15 @@ sealed class DynamicTypeWrapper : TypeWrapper
TypeWrapper[] implementers = GetGhostImplementers(wrapper); TypeWrapper[] implementers = GetGhostImplementers(wrapper);
for(int i = 0; i < implementers.Length; i++) for(int i = 0; i < implementers.Length; i++)
{ {
mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, wrapper.TypeAsParameterType, new Type[] { implementers[i].TypeAsParameterType }); mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, wrapper.TypeAsSignatureType, new Type[] { implementers[i].TypeAsSignatureType });
AttributeHelper.HideFromJava(mb); AttributeHelper.HideFromJava(mb);
ilgen = mb.GetILGenerator(); ilgen = mb.GetILGenerator();
local = ilgen.DeclareLocal(wrapper.TypeAsParameterType); local = ilgen.DeclareLocal(wrapper.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Stfld, wrapper.GhostRefField); ilgen.Emit(OpCodes.Stfld, wrapper.GhostRefField);
ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldobj, wrapper.TypeAsParameterType); ilgen.Emit(OpCodes.Ldobj, wrapper.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ret); ilgen.Emit(OpCodes.Ret);
} }
// Implement the "IsInstance" method // Implement the "IsInstance" method
@ -3005,12 +2997,12 @@ sealed class DynamicTypeWrapper : TypeWrapper
ilgen.Emit(OpCodes.Castclass, wrapper.TypeAsBaseType); ilgen.Emit(OpCodes.Castclass, wrapper.TypeAsBaseType);
ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Pop);
ilgen.MarkLabel(end); ilgen.MarkLabel(end);
local = ilgen.DeclareLocal(wrapper.TypeAsParameterType); local = ilgen.DeclareLocal(wrapper.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Stfld, wrapper.ghostRefField); ilgen.Emit(OpCodes.Stfld, wrapper.ghostRefField);
ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldobj, wrapper.TypeAsParameterType); ilgen.Emit(OpCodes.Ldobj, wrapper.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ret); ilgen.Emit(OpCodes.Ret);
// Add "ToObject" methods // Add "ToObject" methods
mb = typeBuilder.DefineMethod("ToObject", MethodAttributes.Public, typeof(object), Type.EmptyTypes); mb = typeBuilder.DefineMethod("ToObject", MethodAttributes.Public, typeof(object), Type.EmptyTypes);
@ -3252,15 +3244,15 @@ sealed class DynamicTypeWrapper : TypeWrapper
// TODO do this for indirectly implemented interfaces (interfaces implemented by interfaces) as well // TODO do this for indirectly implemented interfaces (interfaces implemented by interfaces) as well
if(interfaces[i].IsGhost) if(interfaces[i].IsGhost)
{ {
MethodBuilder mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, interfaces[i].TypeAsParameterType, new Type[] { wrapper.TypeAsParameterType }); MethodBuilder mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, interfaces[i].TypeAsSignatureType, new Type[] { wrapper.TypeAsSignatureType });
AttributeHelper.HideFromJava(mb); AttributeHelper.HideFromJava(mb);
ILGenerator ilgen = mb.GetILGenerator(); ILGenerator ilgen = mb.GetILGenerator();
LocalBuilder local = ilgen.DeclareLocal(interfaces[i].TypeAsParameterType); LocalBuilder local = ilgen.DeclareLocal(interfaces[i].TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Stfld, interfaces[i].GhostRefField); ilgen.Emit(OpCodes.Stfld, interfaces[i].GhostRefField);
ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldobj, interfaces[i].TypeAsParameterType); ilgen.Emit(OpCodes.Ldobj, interfaces[i].TypeAsSignatureType);
ilgen.Emit(OpCodes.Ret); ilgen.Emit(OpCodes.Ret);
} }
interfaces[i].ImplementInterfaceMethodStubs(typeBuilder, wrapper, doneSet); interfaces[i].ImplementInterfaceMethodStubs(typeBuilder, wrapper, doneSet);
@ -3321,13 +3313,13 @@ sealed class DynamicTypeWrapper : TypeWrapper
if(f.ConstantValue != null) if(f.ConstantValue != null)
{ {
FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal; FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
FieldBuilder fb = tbFields.DefineField(f.Name, typeWrapper.TypeAsFieldType, attribs); FieldBuilder fb = tbFields.DefineField(f.Name, typeWrapper.TypeAsSignatureType, attribs);
fb.SetConstant(f.ConstantValue); fb.SetConstant(f.ConstantValue);
} }
else else
{ {
FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly; FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly;
FieldBuilder fb = tbFields.DefineField(f.Name, typeWrapper.TypeAsFieldType, attribs); FieldBuilder fb = tbFields.DefineField(f.Name, typeWrapper.TypeAsSignatureType, attribs);
if(ilgenClinit == null) if(ilgenClinit == null)
{ {
ilgenClinit = tbFields.DefineTypeInitializer().GetILGenerator(); ilgenClinit = tbFields.DefineTypeInitializer().GetILGenerator();
@ -3406,14 +3398,14 @@ sealed class DynamicTypeWrapper : TypeWrapper
Type[] argTypes = new Type[args.Length + instance + 1]; Type[] argTypes = new Type[args.Length + instance + 1];
if(instance != 0) if(instance != 0)
{ {
argTypes[0] = wrapper.TypeAsParameterType; argTypes[0] = wrapper.TypeAsSignatureType;
} }
for(int i = 0; i < args.Length; i++) for(int i = 0; i < args.Length; i++)
{ {
argTypes[i + instance] = args[i].TypeAsParameterType; argTypes[i + instance] = args[i].TypeAsSignatureType;
} }
argTypes[argTypes.Length - 1] = typeof(RuntimeMethodHandle); argTypes[argTypes.Length - 1] = typeof(RuntimeMethodHandle);
MethodBuilder mb = tb.DefineMethod("method", MethodAttributes.Public | MethodAttributes.Static, mw.ReturnType.TypeAsParameterType, argTypes); MethodBuilder mb = tb.DefineMethod("method", MethodAttributes.Public | MethodAttributes.Static, mw.ReturnType.TypeAsSignatureType, argTypes);
JniBuilder.Generate(mb.GetILGenerator(), wrapper, mw, tb, classFile, m, args, true); JniBuilder.Generate(mb.GetILGenerator(), wrapper, mw, tb, classFile, m, args, true);
for(int i = 0; i < argTypes.Length - 1; i++) for(int i = 0; i < argTypes.Length - 1; i++)
{ {
@ -3507,7 +3499,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
ilGenerator.Emit(OpCodes.Stloc, jnienv); ilGenerator.Emit(OpCodes.Stloc, jnienv);
Label tryBlock = ilGenerator.BeginExceptionBlock(); Label tryBlock = ilGenerator.BeginExceptionBlock();
TypeWrapper retTypeWrapper = mw.ReturnType; TypeWrapper retTypeWrapper = mw.ReturnType;
if(!retTypeWrapper.IsPrimitive) if(!retTypeWrapper.IsUnloadable && !retTypeWrapper.IsPrimitive)
{ {
// this one is for use after we return from "calli" // this one is for use after we return from "calli"
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
@ -3518,7 +3510,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
modargs[1] = typeof(IntPtr); modargs[1] = typeof(IntPtr);
for(int i = 0; i < args.Length; i++) for(int i = 0; i < args.Length; i++)
{ {
modargs[i + 2] = args[i].TypeAsParameterType; modargs[i + 2] = args[i].TypeAsSignatureType;
} }
int add = 0; int add = 0;
if(!m.IsStatic) if(!m.IsStatic)
@ -3548,11 +3540,20 @@ sealed class DynamicTypeWrapper : TypeWrapper
if(!args[j].IsPrimitive) if(!args[j].IsPrimitive)
{ {
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct); ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
if(args[j].IsNonPrimitiveValueType) if(args[j].IsNonPrimitiveValueType)
{ {
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
args[j].EmitBox(ilGenerator); args[j].EmitBox(ilGenerator);
} }
else if(args[j].IsGhost)
{
ilGenerator.Emit(OpCodes.Ldarga_S, (byte)(j + add));
ilGenerator.Emit(OpCodes.Ldfld, args[j].GhostRefField);
}
else
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
}
ilGenerator.Emit(OpCodes.Call, makeLocalRef); ilGenerator.Emit(OpCodes.Call, makeLocalRef);
modargs[j + 2] = typeof(IntPtr); modargs[j + 2] = typeof(IntPtr);
} }
@ -3562,7 +3563,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
} }
} }
ilGenerator.Emit(OpCodes.Ldsfld, methodPtr); ilGenerator.Emit(OpCodes.Ldsfld, methodPtr);
ilGenerator.EmitCalli(OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, (retTypeWrapper.IsPrimitive) ? retTypeWrapper.TypeAsParameterType : typeof(IntPtr), modargs); ilGenerator.EmitCalli(OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, (retTypeWrapper.IsPrimitive) ? retTypeWrapper.TypeAsSignatureType : typeof(IntPtr), modargs);
LocalBuilder retValue = null; LocalBuilder retValue = null;
if(retTypeWrapper != PrimitiveTypeWrapper.VOID) if(retTypeWrapper != PrimitiveTypeWrapper.VOID)
{ {
@ -3573,12 +3574,22 @@ sealed class DynamicTypeWrapper : TypeWrapper
{ {
retTypeWrapper.EmitUnbox(ilGenerator); retTypeWrapper.EmitUnbox(ilGenerator);
} }
else if(!retTypeWrapper.IsGhost) else if(retTypeWrapper.IsGhost)
{
LocalBuilder ghost = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
LocalBuilder obj = ilGenerator.DeclareLocal(typeof(object));
ilGenerator.Emit(OpCodes.Stloc, obj);
ilGenerator.Emit(OpCodes.Ldloca, ghost);
ilGenerator.Emit(OpCodes.Ldloc, obj);
ilGenerator.Emit(OpCodes.Stfld, retTypeWrapper.GhostRefField);
ilGenerator.Emit(OpCodes.Ldloc, ghost);
}
else
{ {
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD); ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD);
} }
} }
retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsParameterType); retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Stloc, retValue); ilGenerator.Emit(OpCodes.Stloc, retValue);
} }
ilGenerator.BeginCatchBlock(typeof(object)); ilGenerator.BeginCatchBlock(typeof(object));
@ -5069,7 +5080,7 @@ sealed class DotNetTypeWrapper : TypeWrapper
{ {
modifiers |= Modifiers.Final; modifiers |= Modifiers.Final;
} }
if(type.IsAbstract) else if(type.IsAbstract) // we can't be abstract if we're final
{ {
modifiers |= Modifiers.Abstract; modifiers |= Modifiers.Abstract;
} }
@ -5374,8 +5385,9 @@ sealed class DotNetTypeWrapper : TypeWrapper
internal override void EmitCall(ILGenerator ilgen) internal override void EmitCall(ILGenerator ilgen)
{ {
// NOTE we don't support custom boxing rules for enums // We don't actually need to do anything here!
ilgen.Emit(OpCodes.Box, ((DotNetTypeWrapper)DeclaringType).type); // The compiler will insert a boxing operation after calling us and that will
// result in our argument being boxed (since that's still sitting on the stack).
} }
internal override object Invoke(object obj, object[] args, bool nonVirtual) internal override object Invoke(object obj, object[] args, bool nonVirtual)
@ -5432,13 +5444,13 @@ sealed class DotNetTypeWrapper : TypeWrapper
} }
// this method takes a boxed Enum and returns its value as a boxed primitive // this method takes a boxed Enum and returns its value as a boxed primitive
// of the subset of Java primitives (i.e. sbyte, short, int, long) // of the subset of Java primitives (i.e. byte, short, int, long)
internal static object GetEnumPrimitiveValue(object obj) internal static object GetEnumPrimitiveValue(object obj)
{ {
Type underlyingType = Enum.GetUnderlyingType(obj.GetType()); Type underlyingType = Enum.GetUnderlyingType(obj.GetType());
if(underlyingType == typeof(sbyte) || underlyingType == typeof(byte)) if(underlyingType == typeof(sbyte) || underlyingType == typeof(byte))
{ {
return unchecked((sbyte)((IConvertible)obj).ToInt32(null)); return unchecked((byte)((IConvertible)obj).ToInt32(null));
} }
else if(underlyingType == typeof(short) || underlyingType == typeof(ushort)) else if(underlyingType == typeof(short) || underlyingType == typeof(ushort))
{ {
@ -5512,9 +5524,9 @@ sealed class DotNetTypeWrapper : TypeWrapper
if(type.IsEnum) if(type.IsEnum)
{ {
Type underlyingType = Enum.GetUnderlyingType(type); Type underlyingType = Enum.GetUnderlyingType(type);
if(underlyingType == typeof(byte)) if(underlyingType == typeof(sbyte))
{ {
underlyingType = typeof(sbyte); underlyingType = typeof(byte);
} }
else if(underlyingType == typeof(ushort)) else if(underlyingType == typeof(ushort))
{ {
@ -5631,6 +5643,7 @@ sealed class DotNetTypeWrapper : TypeWrapper
// (otherwise the type appears abstract while it isn't) // (otherwise the type appears abstract while it isn't)
if(!type.IsAbstract) if(!type.IsAbstract)
{ {
Hashtable clash = null;
Type[] interfaces = type.GetInterfaces(); Type[] interfaces = type.GetInterfaces();
for(int i = 0; i < interfaces.Length; i++) for(int i = 0; i < interfaces.Length; i++)
{ {
@ -5653,8 +5666,19 @@ sealed class DotNetTypeWrapper : TypeWrapper
continue; continue;
} }
} }
// TODO handle name/signature clash if(clash == null)
methodsList.Add(CreateMethodWrapper(name, sig, map.InterfaceMethods[j], true)); {
clash = new Hashtable();
foreach(MethodWrapper mw in methodsList)
{
clash.Add(mw.Name + mw.Signature, null);
}
}
if(!clash.ContainsKey(name + sig))
{
clash.Add(name + sig, null);
methodsList.Add(CreateMethodWrapper(name, sig, map.InterfaceMethods[j], true));
}
} }
} }
} }

Просмотреть файл

@ -418,7 +418,7 @@ namespace IKVM.Attributes
this.val = val; this.val = val;
} }
public ConstantValueAttribute(sbyte val) public ConstantValueAttribute(byte val)
{ {
this.val = val; this.val = val;
} }

Просмотреть файл

@ -164,6 +164,13 @@ namespace IKVM.NativeCode.java
throw JavaException.IllegalArgumentException("primitive wrapper null"); throw JavaException.IllegalArgumentException("primitive wrapper null");
} }
argsCopy[i] = JVM.Library.unbox(args[i]); argsCopy[i] = JVM.Library.unbox(args[i]);
// NOTE we depend on the fact that the .NET reflection parameter type
// widening rules are the same as in Java, but to have this work for byte
// we need to convert byte to sbyte.
if(argsCopy[i] is byte && argWrappers[i] != PrimitiveTypeWrapper.BYTE)
{
argsCopy[i] = (sbyte)(byte)argsCopy[i];
}
} }
else else
{ {
@ -221,16 +228,6 @@ namespace IKVM.NativeCode.java
return VMClass.getWrapperFromClass(a).IsInSamePackageAs(VMClass.getWrapperFromClass(b)); return VMClass.getWrapperFromClass(a).IsInSamePackageAs(VMClass.getWrapperFromClass(b));
} }
public static object getClassFromFrame(NetSystem.Diagnostics.StackFrame frame)
{
Type type = frame.GetMethod().DeclaringType;
if(type == null)
{
return null;
}
return VMClass.getClassFromType(type);
}
public static object GetValue(object fieldCookie, object o) public static object GetValue(object fieldCookie, object o)
{ {
Profiler.Enter("Field.GetValue"); Profiler.Enter("Field.GetValue");
@ -272,6 +269,13 @@ namespace IKVM.NativeCode.java
if(wrapper.FieldTypeWrapper.IsPrimitive) if(wrapper.FieldTypeWrapper.IsPrimitive)
{ {
v = JVM.Library.unbox(v); v = JVM.Library.unbox(v);
// NOTE we depend on the fact that the .NET reflection parameter type
// widening rules are the same as in Java, but to have this work for byte
// we need to convert byte to sbyte.
if(v is byte && wrapper.FieldTypeWrapper != PrimitiveTypeWrapper.BYTE)
{
v = (sbyte)(byte)v;
}
} }
// if the field is an interface field, we must explicitly run <clinit>, // if the field is an interface field, we must explicitly run <clinit>,
// because .NET reflection doesn't // because .NET reflection doesn't
@ -291,9 +295,9 @@ namespace IKVM.NativeCode.java
public class VMRuntime public class VMRuntime
{ {
public static int nativeLoad(string filename) public static int nativeLoad(string filename, object classLoader)
{ {
return IKVM.Runtime.JniHelper.LoadLibrary(filename); return IKVM.Runtime.JniHelper.LoadLibrary(filename, ClassLoaderWrapper.GetClassLoaderWrapper(classLoader));
} }
} }
@ -541,50 +545,6 @@ namespace IKVM.NativeCode.java
} }
} }
public class VMSecurityManager
{
public static object getClassContext()
{
ArrayList ar = new ArrayList();
NetSystem.Diagnostics.StackTrace st = new NetSystem.Diagnostics.StackTrace();
for(int i = 0; i < st.FrameCount; i++)
{
NetSystem.Diagnostics.StackFrame frame = st.GetFrame(i);
// HACK very insecure
// TODO handle reflection scenario
if(frame.GetMethod().Name != "getClassContext")
{
Type type = frame.GetMethod().DeclaringType;
if(type != null)
{
ar.Add(VMClass.getClassFromType(type));
}
}
}
return ar.ToArray(CoreClasses.java.lang.Class.Wrapper.TypeAsArrayType);
}
public static object currentClassLoader()
{
// TODO handle PrivilegedAction
NetSystem.Diagnostics.StackTrace st = new NetSystem.Diagnostics.StackTrace();
for(int i = 0; i < st.FrameCount; i++)
{
NetSystem.Diagnostics.StackFrame frame = st.GetFrame(i);
Type type = frame.GetMethod().DeclaringType;
if(type != null)
{
TypeWrapper wrapper = ClassLoaderWrapper.GetWrapperFromTypeFast(type);
if(wrapper != null && wrapper.GetClassLoader().GetJavaClassLoader() != null)
{
return wrapper.GetClassLoader().GetJavaClassLoader();
}
}
}
return null;
}
}
public class VMSystem public class VMSystem
{ {
public static void arraycopy(object src, int srcStart, object dest, int destStart, int len) public static void arraycopy(object src, int srcStart, object dest, int destStart, int len)
@ -723,6 +683,22 @@ namespace IKVM.NativeCode.java
Profiler.Leave("ClassLoader.defineClass"); Profiler.Leave("ClassLoader.defineClass");
} }
} }
public static string getPackageName(Type type)
{
// TODO consider optimizing this (by getting the type name without constructing the TypeWrapper)
string name = ClassLoaderWrapper.GetWrapperFromType(type).Name;
// if we process mscorlib and we encounter a primitive, the name will be null
if(name != null)
{
int dot = name.LastIndexOf('.');
if(dot > 0)
{
return name.Substring(0, dot);
}
}
return null;
}
} }
public class VMClass public class VMClass
@ -1162,7 +1138,7 @@ namespace IKVM.NativeCode.java
GetFieldWrapperFromField(field).SetValue(obj, val); GetFieldWrapperFromField(field).SetValue(obj, val);
} }
public static void setByteNative(object field, object obj, sbyte val) public static void setByteNative(object field, object obj, byte val)
{ {
GetFieldWrapperFromField(field).SetValue(obj, val); GetFieldWrapperFromField(field).SetValue(obj, val);
} }
@ -1185,7 +1161,21 @@ namespace IKVM.NativeCode.java
// TODO calling currentClassLoader in SecurityManager results in null being returned, so we use our own // TODO calling currentClassLoader in SecurityManager results in null being returned, so we use our own
// version for now, don't know what the security implications of this are // version for now, don't know what the security implications of this are
// SECURITY // SECURITY
return NativeCode.java.lang.VMSecurityManager.currentClassLoader(); NetSystem.Diagnostics.StackTrace st = new NetSystem.Diagnostics.StackTrace();
for(int i = 0; i < st.FrameCount; i++)
{
NetSystem.Diagnostics.StackFrame frame = st.GetFrame(i);
Type type = frame.GetMethod().DeclaringType;
if(type != null)
{
TypeWrapper wrapper = ClassLoaderWrapper.GetWrapperFromTypeFast(type);
if(wrapper != null && wrapper.GetClassLoader().GetJavaClassLoader() != null)
{
return wrapper.GetClassLoader().GetJavaClassLoader();
}
}
}
return null;
} }
public static object allocateObject(object ois, object clazz, object constructor_clazz, object constructor) public static object allocateObject(object ois, object clazz, object constructor_clazz, object constructor)
@ -1223,9 +1213,9 @@ namespace IKVM.NativeCode.java
{ {
public class InetAddress public class InetAddress
{ {
public static sbyte[] lookupInaddrAny() public static byte[] lookupInaddrAny()
{ {
return new sbyte[] { 0, 0, 0, 0 }; return new byte[] { 0, 0, 0, 0 };
} }
public static string getLocalHostname() public static string getLocalHostname()
@ -1234,23 +1224,17 @@ namespace IKVM.NativeCode.java
return NetSystem.Net.Dns.GetHostName(); return NetSystem.Net.Dns.GetHostName();
} }
public static sbyte[][] getHostByName(string name) public static byte[][] getHostByName(string name)
{ {
// TODO error handling // TODO error handling
try try
{ {
NetSystem.Net.IPHostEntry he = NetSystem.Net.Dns.GetHostByName(name); NetSystem.Net.IPHostEntry he = NetSystem.Net.Dns.GetHostByName(name);
NetSystem.Net.IPAddress[] addresses = he.AddressList; NetSystem.Net.IPAddress[] addresses = he.AddressList;
sbyte[][] list = new sbyte[addresses.Length][]; byte[][] list = new byte[addresses.Length][];
for(int i = 0; i < addresses.Length; i++) for(int i = 0; i < addresses.Length; i++)
{ {
byte[] address = addresses[i].GetAddressBytes(); list[i] = addresses[i].GetAddressBytes();
sbyte[] sb = new sbyte[address.Length];
for(int j = 0; j < sb.Length; j++)
{
sb[j] = (sbyte)address[j];
}
list[i] = sb;
} }
return list; return list;
} }
@ -1392,6 +1376,31 @@ namespace IKVM.NativeCode.gnu.classpath
return typeof(VMSystemProperties).Assembly.GetName().Version.ToString(); return typeof(VMSystemProperties).Assembly.GetName().Version.ToString();
} }
} }
public class VMStackWalker
{
internal static volatile Assembly nonVirtualInvokeAssembly;
public static object getClassFromType(Type type)
{
return IKVM.NativeCode.java.lang.VMClass.getClassFromType(type);
}
public static object getClassLoaderFromType(Type type)
{
return IKVM.NativeCode.java.lang.VMClass.getClassLoaderFromType(type);
}
public static Type getJNIEnvType()
{
return typeof(IKVM.Runtime.JNIEnv);
}
public static Assembly getNonVirtualInvokeAssembly()
{
return nonVirtualInvokeAssembly;
}
}
} }
namespace gnu.classpath namespace gnu.classpath
@ -1401,11 +1410,11 @@ namespace gnu.classpath
public unsafe sealed class RawData public unsafe sealed class RawData
{ {
[HideFromJava] [HideFromJava]
private sbyte* pb; private byte* pb;
public RawData(IntPtr p) public RawData(IntPtr p)
{ {
this.pb = (sbyte*)p; this.pb = (byte*)p;
} }
public IntPtr p() public IntPtr p()
@ -1417,13 +1426,13 @@ namespace gnu.classpath
// security attribute isn't really needed, but to be extra safe we add the explicit link // security attribute isn't really needed, but to be extra safe we add the explicit link
// demand to these dangerous methods. // demand to these dangerous methods.
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)] [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public sbyte ReadByte(int index) public byte ReadByte(int index)
{ {
return pb[index]; return pb[index];
} }
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)] [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public void WriteByte(int index, sbyte b) public void WriteByte(int index, byte b)
{ {
pb[index] = b; pb[index] = b;
} }
@ -1467,6 +1476,7 @@ namespace ikvm.@internal
void jniWaitUntilLastThread(); void jniWaitUntilLastThread();
void jniDetach(); void jniDetach();
void setThreadGroup(object group);
object newConstructor(object clazz, object wrapper); object newConstructor(object clazz, object wrapper);
object newMethod(object clazz, object wrapper); object newMethod(object clazz, object wrapper);

Просмотреть файл

@ -1,5 +1,5 @@
/* /*
Copyright (C) 2002, 2003, 2004 Jeroen Frijters Copyright (C) 2002, 2003, 2004, 2005 Jeroen Frijters
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -175,8 +175,9 @@ class Compiler
{ {
tw = args[arg - 1]; tw = args[arg - 1];
} }
if(v.type != VerifierTypeWrapper.UninitializedThis && if(!tw.IsUnloadable &&
(v.type != tw || tw.TypeAsLocalOrStackType != tw.TypeAsParameterType)) v.type != VerifierTypeWrapper.UninitializedThis &&
(v.type != tw || tw.TypeAsLocalOrStackType != tw.TypeAsSignatureType))
{ {
v.builder = ilGenerator.DeclareLocal(v.type.TypeAsLocalOrStackType); v.builder = ilGenerator.DeclareLocal(v.type.TypeAsLocalOrStackType);
if(JVM.Debug && v.name != null) if(JVM.Debug && v.name != null)
@ -185,7 +186,7 @@ class Compiler
} }
v.isArg = false; v.isArg = false;
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)arg); ilGenerator.Emit(OpCodes.Ldarg_S, (byte)arg);
v.type.EmitConvParameterToStackType(ilGenerator); tw.EmitConvSignatureTypeToStackType(ilGenerator);
ilGenerator.Emit(OpCodes.Stloc, v.builder); ilGenerator.Emit(OpCodes.Stloc, v.builder);
} }
} }
@ -1421,6 +1422,7 @@ class Compiler
// we must emit code to cast the stack value to the interface type // we must emit code to cast the stack value to the interface type
CastInterfaceArgs(method, cpi.GetArgTypes(), i, false, false); CastInterfaceArgs(method, cpi.GetArgTypes(), i, false, false);
method.EmitCall(ilGenerator); method.EmitCall(ilGenerator);
method.ReturnType.EmitConvSignatureTypeToStackType(ilGenerator);
break; break;
} }
case NormalizedByteCode.__invokevirtual: case NormalizedByteCode.__invokevirtual:
@ -1614,6 +1616,7 @@ class Compiler
{ {
method.EmitCallvirt(ilGenerator); method.EmitCallvirt(ilGenerator);
} }
method.ReturnType.EmitConvSignatureTypeToStackType(ilGenerator);
} }
break; break;
} }
@ -1631,12 +1634,12 @@ class Compiler
if(instr.NormalizedOpCode != NormalizedByteCode.__return) if(instr.NormalizedOpCode != NormalizedByteCode.__return)
{ {
TypeWrapper retTypeWrapper = mw.ReturnType; TypeWrapper retTypeWrapper = mw.ReturnType;
retTypeWrapper.EmitConvStackToParameterType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0)); retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0));
if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable)
{ {
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsParameterType); ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsSignatureType);
} }
local = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsParameterType); local = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Stloc, local); ilGenerator.Emit(OpCodes.Stloc, local);
} }
Label label = ilGenerator.DefineLabel(); Label label = ilGenerator.DefineLabel();
@ -1660,14 +1663,14 @@ class Compiler
else else
{ {
TypeWrapper retTypeWrapper = mw.ReturnType; TypeWrapper retTypeWrapper = mw.ReturnType;
retTypeWrapper.EmitConvStackToParameterType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0)); retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0));
if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable)
{ {
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsParameterType); ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsSignatureType);
} }
if(stackHeight != 1) if(stackHeight != 1)
{ {
LocalBuilder local = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsParameterType); LocalBuilder local = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Stloc, local); ilGenerator.Emit(OpCodes.Stloc, local);
ilGenerator.Emit(OpCodes.Leave_S, (byte)0); ilGenerator.Emit(OpCodes.Leave_S, (byte)0);
ilGenerator.Emit(OpCodes.Ldloc, local); ilGenerator.Emit(OpCodes.Ldloc, local);
@ -2809,7 +2812,7 @@ class Compiler
} }
else else
{ {
LocalBuilder local = ilGenerator.DeclareLocal(args[i].TypeAsParameterType); LocalBuilder local = ilGenerator.DeclareLocal(args[i].TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Ldloca, local); ilGenerator.Emit(OpCodes.Ldloca, local);
dh.Load(i); dh.Load(i);
ilGenerator.Emit(OpCodes.Stfld, args[i].GhostRefField); ilGenerator.Emit(OpCodes.Stfld, args[i].GhostRefField);
@ -2817,7 +2820,7 @@ class Compiler
// NOTE when the this argument is a value type, we need the address on the stack instead of the value // NOTE when the this argument is a value type, we need the address on the stack instead of the value
if(i != 0 || !instanceMethod) if(i != 0 || !instanceMethod)
{ {
ilGenerator.Emit(OpCodes.Ldobj, args[i].TypeAsParameterType); ilGenerator.Emit(OpCodes.Ldobj, args[i].TypeAsSignatureType);
} }
} }
} }
@ -2843,7 +2846,7 @@ class Compiler
} }
else if(ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i).IsUnloadable) else if(ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i).IsUnloadable)
{ {
ilGenerator.Emit(OpCodes.Castclass, args[i].TypeAsParameterType); ilGenerator.Emit(OpCodes.Castclass, args[i].TypeAsSignatureType);
} }
} }
} }
@ -2925,16 +2928,14 @@ class Compiler
if(!write) if(!write)
{ {
field.EmitGet(ilGenerator); field.EmitGet(ilGenerator);
field.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilGenerator);
return; return;
} }
else else
{ {
TypeWrapper tw = field.FieldTypeWrapper; TypeWrapper tw = field.FieldTypeWrapper;
TypeWrapper val = ma.GetRawStackTypeWrapper(i, 0); TypeWrapper val = ma.GetRawStackTypeWrapper(i, 0);
if(!tw.IsUnloadable && (val.IsUnloadable || (tw.IsInterfaceOrInterfaceArray && !tw.IsGhost && !val.IsAssignableTo(tw)))) tw.EmitConvStackTypeToSignatureType(ilGenerator, val);
{
ilGenerator.Emit(OpCodes.Castclass, tw.TypeAsTBD);
}
field.EmitSet(ilGenerator); field.EmitSet(ilGenerator);
return; return;
} }
@ -2972,6 +2973,10 @@ class Compiler
// NOTE we don't need to use TypeWrapper.EmitUnbox, because the return value cannot be null // NOTE we don't need to use TypeWrapper.EmitUnbox, because the return value cannot be null
ilgen.Emit(OpCodes.Unbox, typeWrapper.TypeAsTBD); ilgen.Emit(OpCodes.Unbox, typeWrapper.TypeAsTBD);
ilgen.Emit(OpCodes.Ldobj, typeWrapper.TypeAsTBD); ilgen.Emit(OpCodes.Ldobj, typeWrapper.TypeAsTBD);
if(typeWrapper == PrimitiveTypeWrapper.BYTE)
{
ilgen.Emit(OpCodes.Conv_I1);
}
} }
else else
{ {
@ -2989,7 +2994,7 @@ class Compiler
private ClassFile.ConstantPoolItemMI cpi; private ClassFile.ConstantPoolItemMI cpi;
internal DynamicMethodWrapper(ClassLoaderWrapper classLoader, TypeWrapper wrapper, ClassFile.ConstantPoolItemMI cpi) internal DynamicMethodWrapper(ClassLoaderWrapper classLoader, TypeWrapper wrapper, ClassFile.ConstantPoolItemMI cpi)
: base(wrapper, null, null, null, null, null, Modifiers.Public, MemberFlags.None) : base(wrapper, cpi.Name, cpi.Signature, null, cpi.GetRetType(), cpi.GetArgTypes(), Modifiers.Public, MemberFlags.None)
{ {
this.classLoader = classLoader; this.classLoader = classLoader;
this.wrapper = wrapper; this.wrapper = wrapper;

Просмотреть файл

@ -145,9 +145,9 @@ namespace IKVM.Internal.MapXml
} }
if(tw.IsGhost) if(tw.IsGhost)
{ {
tw.EmitConvStackToParameterType(ilgen, tw); tw.EmitConvStackTypeToSignatureType(ilgen, tw);
} }
temps[j] = ilgen.DeclareLocal(tw.TypeAsParameterType); temps[j] = ilgen.DeclareLocal(tw.TypeAsSignatureType);
ilgen.Emit(OpCodes.Stloc, temps[j]); ilgen.Emit(OpCodes.Stloc, temps[j]);
} }
for(int j = 0; j < temps.Length; j++) for(int j = 0; j < temps.Length; j++)
@ -672,8 +672,7 @@ namespace IKVM.Internal.MapXml
{ {
FieldWrapper fw = ClassLoaderWrapper.LoadClassCritical(Class).GetFieldWrapper(Name, Sig); FieldWrapper fw = ClassLoaderWrapper.LoadClassCritical(Class).GetFieldWrapper(Name, Sig);
fw.Link(); fw.Link();
// we don't use fw.EmitGet because we don't want automatic boxing and whatever fw.EmitGet(ilgen);
ilgen.Emit(OpCodes.Ldfld, fw.GetField());
} }
} }

Просмотреть файл

@ -31,6 +31,7 @@ using System.Collections;
using System.Xml; using System.Xml;
using System.Diagnostics; using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Text;
using IKVM.Attributes; using IKVM.Attributes;
using IKVM.Runtime; using IKVM.Runtime;
@ -99,7 +100,7 @@ namespace IKVM.Runtime
{ {
ArrayList list = new ArrayList(); ArrayList list = new ArrayList();
string cmdline = Environment.CommandLine; string cmdline = Environment.CommandLine;
System.Text.StringBuilder sb = new System.Text.StringBuilder(); StringBuilder sb = new StringBuilder();
for(int i = 0; i < cmdline.Length;) for(int i = 0; i < cmdline.Length;)
{ {
bool quoted = cmdline[i] == '"'; bool quoted = cmdline[i] == '"';
@ -406,7 +407,7 @@ namespace IKVM.Internal
// but in order for ILDASM/ILASM round tripping to work reliably, we have // but in order for ILDASM/ILASM round tripping to work reliably, we have
// to make sure that we don't produce resource names that'll cause ILDASM // to make sure that we don't produce resource names that'll cause ILDASM
// to generate invalid filenames. // to generate invalid filenames.
System.Text.StringBuilder sb = new System.Text.StringBuilder("ikvm__", name.Length + 6); StringBuilder sb = new StringBuilder("ikvm__", name.Length + 6);
foreach(char c in name) foreach(char c in name)
{ {
if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+.()$#@~=&{}[]0123456789`".IndexOf(c) != -1) if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+.()$#@~=&{}[]0123456789`".IndexOf(c) != -1)
@ -1121,7 +1122,7 @@ namespace IKVM.Internal
typeWrapper.helperTypeBuilder = typeWrapper.typeBuilder.DefineNestedType("__Helper", TypeAttributes.NestedPublic | TypeAttributes.Class); typeWrapper.helperTypeBuilder = typeWrapper.typeBuilder.DefineNestedType("__Helper", TypeAttributes.NestedPublic | TypeAttributes.Class);
AttributeHelper.HideFromJava(typeWrapper.helperTypeBuilder); AttributeHelper.HideFromJava(typeWrapper.helperTypeBuilder);
} }
helper = typeWrapper.helperTypeBuilder.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.Static, typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig).TypeAsParameterType, argTypes); helper = typeWrapper.helperTypeBuilder.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.Static, typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig).TypeAsSignatureType, argTypes);
ILGenerator ilgen = helper.GetILGenerator(); ILGenerator ilgen = helper.GetILGenerator();
foreach(IKVM.Internal.MapXml.Class c in specialCases) foreach(IKVM.Internal.MapXml.Class c in specialCases)
{ {
@ -1156,7 +1157,7 @@ namespace IKVM.Internal
{ {
MethodBuilder mbCore = null; MethodBuilder mbCore = null;
Type[] paramTypes = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig); Type[] paramTypes = typeWrapper.GetClassLoader().ArgTypeListFromSig(m.Sig);
Type retType = typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig).TypeAsParameterType; Type retType = typeWrapper.GetClassLoader().RetTypeWrapperFromSig(m.Sig).TypeAsSignatureType;
if(typeWrapper.shadowType.IsSealed && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0) if(typeWrapper.shadowType.IsSealed && (m.Modifiers & IKVM.Internal.MapXml.MapModifiers.Static) == 0)
{ {
@ -1276,7 +1277,7 @@ namespace IKVM.Internal
{ {
if(instr is IKVM.Internal.MapXml.Ret) if(instr is IKVM.Internal.MapXml.Ret)
{ {
this.ReturnType.EmitConvStackToParameterType(ilgen, null); this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
} }
instr.Generate(context, ilgen); instr.Generate(context, ilgen);
} }
@ -1309,7 +1310,7 @@ namespace IKVM.Internal
} }
ilgen.Emit(OpCodes.Call, baseMethod); ilgen.Emit(OpCodes.Call, baseMethod);
} }
this.ReturnType.EmitConvStackToParameterType(ilgen, null); this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
ilgen.Emit(OpCodes.Ret); ilgen.Emit(OpCodes.Ret);
} }
ilgen.EmitLineNumberTable(mbCore); ilgen.EmitLineNumberTable(mbCore);
@ -1344,7 +1345,7 @@ namespace IKVM.Internal
ilgen.Emit(OpCodes.Ldarg, (short)(i + 1)); ilgen.Emit(OpCodes.Ldarg, (short)(i + 1));
} }
ilgen.Emit(OpCodes.Callvirt, mbCore); ilgen.Emit(OpCodes.Callvirt, mbCore);
this.ReturnType.EmitConvStackToParameterType(ilgen, null); this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
ilgen.Emit(OpCodes.Ret); ilgen.Emit(OpCodes.Ret);
ilgen.MarkLabel(skip); ilgen.MarkLabel(skip);
ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Pop);
@ -1370,7 +1371,7 @@ namespace IKVM.Internal
} }
mw.Link(); mw.Link();
mw.EmitCallvirt(ilgen); mw.EmitCallvirt(ilgen);
this.ReturnType.EmitConvStackToParameterType(ilgen, null); this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
ilgen.Emit(OpCodes.Ret); ilgen.Emit(OpCodes.Ret);
ilgen.MarkLabel(skip); ilgen.MarkLabel(skip);
ilgen.Emit(OpCodes.Pop); ilgen.Emit(OpCodes.Pop);
@ -1385,7 +1386,7 @@ namespace IKVM.Internal
{ {
if(instr is IKVM.Internal.MapXml.Ret) if(instr is IKVM.Internal.MapXml.Ret)
{ {
this.ReturnType.EmitConvStackToParameterType(ilgen, null); this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
} }
instr.Generate(context, ilgen); instr.Generate(context, ilgen);
} }
@ -1428,7 +1429,7 @@ namespace IKVM.Internal
} }
ilgen.Emit(OpCodes.Callvirt, overrideMethod); ilgen.Emit(OpCodes.Callvirt, overrideMethod);
} }
this.ReturnType.EmitConvStackToParameterType(ilgen, null); this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
ilgen.Emit(OpCodes.Ret); ilgen.Emit(OpCodes.Ret);
} }
ilgen.EmitLineNumberTable(mbHelper); ilgen.EmitLineNumberTable(mbHelper);
@ -1439,7 +1440,7 @@ namespace IKVM.Internal
{ {
RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType; RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType;
Type[] argTypes = new Type[paramTypes.Length + 1]; Type[] argTypes = new Type[paramTypes.Length + 1];
argTypes[0] = typeWrapper.TypeAsParameterType; argTypes[0] = typeWrapper.TypeAsSignatureType;
this.GetParametersForDefineMethod().CopyTo(argTypes, 1); this.GetParametersForDefineMethod().CopyTo(argTypes, 1);
MethodBuilder mb = typeWrapper.typeBuilder.DefineMethod("nonvirtualhelper/" + this.Name, MethodAttributes.Private | MethodAttributes.Static, this.ReturnTypeForDefineMethod, argTypes); MethodBuilder mb = typeWrapper.typeBuilder.DefineMethod("nonvirtualhelper/" + this.Name, MethodAttributes.Private | MethodAttributes.Static, this.ReturnTypeForDefineMethod, argTypes);
AttributeHelper.HideFromJava(mb); AttributeHelper.HideFromJava(mb);
@ -1504,13 +1505,6 @@ namespace IKVM.Internal
mw.Link(); mw.Link();
mw.EmitCall(ilgen); mw.EmitCall(ilgen);
} }
if(!classLoader.RetTypeWrapperFromSig(redirSig).IsAssignableTo(this.ReturnType))
{
// NOTE we're passing a null context, this is safe because the return type
// should always be loadable
System.Diagnostics.Debug.Assert(!this.ReturnType.IsUnloadable);
this.ReturnType.EmitCheckcast(null, ilgen);
}
} }
} }
@ -1570,7 +1564,7 @@ namespace IKVM.Internal
{ {
attr |= FieldAttributes.InitOnly; attr |= FieldAttributes.InitOnly;
} }
FieldBuilder fb = tb.DefineField(f.Name, GetClassLoader().FieldTypeWrapperFromSig(f.Sig).TypeAsFieldType, attr); FieldBuilder fb = tb.DefineField(f.Name, GetClassLoader().FieldTypeWrapperFromSig(f.Sig).TypeAsSignatureType, attr);
object constant; object constant;
if(f.Constant != null) if(f.Constant != null)
{ {
@ -1650,27 +1644,31 @@ namespace IKVM.Internal
Hashtable methods = new Hashtable(); Hashtable methods = new Hashtable();
foreach(MethodInfo mi in typeBuilder.BaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) foreach(MethodInfo mi in typeBuilder.BaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
{ {
ParameterInfo[] paramInfo = mi.GetParameters(); string key = MakeMethodKey(mi);
Type[] paramTypes = new Type[paramInfo.Length]; if(!methods.ContainsKey(key))
for(int i = 0; i < paramInfo.Length; i++)
{ {
paramTypes[i] = paramInfo[i].ParameterType; ParameterInfo[] paramInfo = mi.GetParameters();
Type[] paramTypes = new Type[paramInfo.Length];
for(int i = 0; i < paramInfo.Length; i++)
{
paramTypes[i] = paramInfo[i].ParameterType;
}
MethodBuilder mb = typeBuilder.DefineMethod(mi.Name, mi.Attributes & ~(MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot), mi.ReturnType, paramTypes);
AttributeHelper.HideFromJava(mb);
AttributeHelper.SetEditorBrowsableNever(mb);
ILGenerator ilgen = mb.GetILGenerator();
for(int i = 0; i < paramTypes.Length; i++)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)i);
}
if(!mi.IsStatic)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)paramTypes.Length);
}
ilgen.Emit(OpCodes.Call, mi);
ilgen.Emit(OpCodes.Ret);
methods[key] = mb;
} }
MethodBuilder mb = typeBuilder.DefineMethod(mi.Name, mi.Attributes & ~(MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot), mi.ReturnType, paramTypes);
AttributeHelper.HideFromJava(mb);
AttributeHelper.SetEditorBrowsableNever(mb);
ILGenerator ilgen = mb.GetILGenerator();
for(int i = 0; i < paramTypes.Length; i++)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)i);
}
if(!mi.IsStatic)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)paramTypes.Length);
}
ilgen.Emit(OpCodes.Call, mi);
ilgen.Emit(OpCodes.Ret);
methods[mb.Name] = mb;
} }
foreach(PropertyInfo pi in typeBuilder.BaseType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) foreach(PropertyInfo pi in typeBuilder.BaseType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
{ {
@ -1683,11 +1681,11 @@ namespace IKVM.Internal
PropertyBuilder pb = typeBuilder.DefineProperty(pi.Name, pi.Attributes, pi.PropertyType, paramTypes); PropertyBuilder pb = typeBuilder.DefineProperty(pi.Name, pi.Attributes, pi.PropertyType, paramTypes);
if(pi.CanRead) if(pi.CanRead)
{ {
pb.SetGetMethod((MethodBuilder)methods[pi.GetGetMethod().Name]); pb.SetGetMethod((MethodBuilder)methods[MakeMethodKey(pi.GetGetMethod())]);
} }
if(pi.CanWrite) if(pi.CanWrite)
{ {
pb.SetSetMethod((MethodBuilder)methods[pi.GetSetMethod().Name]); pb.SetSetMethod((MethodBuilder)methods[MakeMethodKey(pi.GetSetMethod())]);
} }
AttributeHelper.SetEditorBrowsableNever(pb); AttributeHelper.SetEditorBrowsableNever(pb);
} }
@ -1700,6 +1698,20 @@ namespace IKVM.Internal
} }
} }
private static string MakeMethodKey(MethodInfo method)
{
StringBuilder sb = new StringBuilder();
sb.Append(method.ReturnType.AssemblyQualifiedName).Append(":").Append(method.Name);
ParameterInfo[] paramInfo = method.GetParameters();
Type[] paramTypes = new Type[paramInfo.Length];
for(int i = 0; i < paramInfo.Length; i++)
{
paramTypes[i] = paramInfo[i].ParameterType;
sb.Append(":").Append(paramInfo[i].ParameterType.AssemblyQualifiedName);
}
return sb.ToString();
}
private void CreateShadowInstanceOf(ICollection remappedTypes) private void CreateShadowInstanceOf(ICollection remappedTypes)
{ {
// FXBUG .NET 1.1 doesn't allow static methods on interfaces // FXBUG .NET 1.1 doesn't allow static methods on interfaces