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
// 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

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

@ -56,6 +56,7 @@ namespace ikvm.awt
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 volatile Form bogusForm;
private static Delegate createControlInstance;
@ -372,7 +373,7 @@ namespace ikvm.awt
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();
}
@ -440,6 +441,42 @@ namespace ikvm.awt
{
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
@ -469,7 +506,7 @@ namespace ikvm.awt
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();
}
@ -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)
{
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)
@ -1743,7 +1781,7 @@ namespace ikvm.awt
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");
}

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

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

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

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

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

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

@ -1,8 +1,10 @@
<?xml version="1.0"?>
<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 overwrite="false" name="signoption" value="" />
<property name="jikes.compiler" value="true" />
<property name="ecj.compiler" value="false" />
<if propertytrue="nant.platform.win32">
<property name="pathsep" value=";" />
@ -25,12 +27,17 @@
<includes name="**.class"/>
</fileset>
</delete>
<if propertytrue="jikes.compiler">
<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 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" />
<if propertytrue="nant.platform.win32">
<call target="peverify-classpath"/>

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

@ -45,7 +45,7 @@ public interface Configuration
{
// TODO
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.AddressFamily;
import ikvm.lang.CIL;
import ikvm.lang.ByteArrayHack;
/**
* This is the default socket implementation for datagram sockets.
@ -166,7 +165,7 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{
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");
}
@ -211,7 +210,7 @@ public class PlainDatagramSocketImpl extends DatagramSocketImpl
{
if(false) throw new cli.System.Net.Sockets.SocketException();
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);
setDatagramPacketLength(packet, length);
}

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

@ -51,7 +51,6 @@ import cli.System.Net.Sockets.ProtocolType;
import cli.System.Net.Sockets.AddressFamily;
import cli.System.Net.Sockets.SocketShutdown;
import ikvm.lang.CIL;
import ikvm.lang.ByteArrayHack;
/**
* 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.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)
{
@ -371,7 +370,7 @@ public class PlainSocketImpl extends SocketImpl
{
if(false) throw new cli.System.Net.Sockets.SocketException();
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)
{
@ -667,7 +666,7 @@ public class PlainSocketImpl extends SocketImpl
if(false) throw new cli.System.Net.Sockets.SocketException();
if(false) throw new cli.System.ObjectDisposedException("");
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)
{

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

@ -81,20 +81,28 @@ class IkvmresURLConnection extends URLConnection
}
try
{
ResourceReader r = new ResourceReader(s);
Object r;
try
{
IEnumerator e = r.GetEnumerator();
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
{
IEnumerator e = ((IEnumerable)r).GetEnumerator();
if(!e.MoveNext())
{
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;
}
finally
{
r.Close();
((cli.System.IDisposable)r).Dispose();
}
}
finally

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

@ -55,7 +55,6 @@ import java.nio.channels.WritableByteChannel;
import cli.System.Console;
import cli.System.IO.*;
import ikvm.lang.ByteArrayHack;
import ikvm.lang.CIL;
/**
@ -382,7 +381,7 @@ public final class FileChannelImpl extends FileChannel
try
{
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)
{
count = -1;
@ -416,6 +415,7 @@ public final class FileChannelImpl extends FileChannel
{
byte[] buffer = src.array();
write(buffer, src.arrayOffset() + src.position(), len);
src.position(src.position() + len);
}
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.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
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.ObjectDisposedException(null);
stream.WriteByte(CIL.box_ubyte((byte)b));
stream.WriteByte((byte)b);
// NOTE FileStream buffers the output, so we have to flush explicitly
stream.Flush();
}

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

@ -42,6 +42,7 @@ public interface LibraryVMInterface
void jniWaitUntilLastThread();
void jniDetach();
void setThreadGroup(Object group);
Object newConstructor(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;
/** @deprecated */
public final class ByteArrayHack
{
private ByteArrayHack() {}
public static native cli.System.Byte[] cast(byte[] b);
public static native byte[] cast(cli.System.Byte[] b);
public static byte[] cast(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
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_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.UInt32 box_uint(int v);
public static native cli.System.UInt64 box_ulong(long v);
public static native byte unbox_ubyte(cli.System.Byte v);
public static native byte unbox_sbyte(cli.System.SByte v);
public static native short unbox_ushort(cli.System.UInt16 v);
public static native int unbox_uint(cli.System.UInt32 v);
public static native long unbox_ulong(cli.System.UInt64 v);

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

@ -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
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)
{
if(val instanceof cli.System.SByte)
if(val instanceof cli.System.Byte)
{
return new Byte(CIL.unbox_byte(val));
}
@ -189,12 +189,17 @@ class LibraryVMInterfaceImpl implements ikvm.internal.LibraryVMInterface
VMThread.jniDetach();
}
public void setThreadGroup(Object group)
{
VMThread.setThreadGroup((ThreadGroup)group);
}
public native Object newDirectByteBuffer(cli.System.IntPtr address, int capacity);
public native cli.System.IntPtr getDirectBufferAddress(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)

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

@ -45,6 +45,7 @@ import java.util.Enumeration;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.StringTokenizer;
import java.lang.reflect.Constructor;
import gnu.classpath.SystemProperties;
@ -172,6 +173,8 @@ final class VMClassLoader
* @throws IOException if one occurs
*/
static Enumeration getResources(String name) throws IOException
{
synchronized(nestedGetResourcesHack)
{
if(cli.System.Threading.Thread.GetData(nestedGetResourcesHack) != null)
{
@ -199,6 +202,7 @@ final class VMClassLoader
cli.System.Threading.Thread.SetData(nestedGetResourcesHack, null);
}
}
}
private static cli.System.LocalDataStoreSlot nestedGetResourcesHack = cli.System.Threading.Thread.AllocateDataSlot();
@ -212,6 +216,14 @@ final class VMClassLoader
*/
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;
}
@ -223,9 +235,96 @@ final class VMClassLoader
* @return all named packages, if any exist
*/
static Package[] getPackages()
{
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

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

@ -189,7 +189,7 @@ final class VMRuntime
* @param filename the file to load
* @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.

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

@ -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)
{
VMThread vmThread = new VMThread(thread);
@ -463,10 +472,9 @@ final class VMThread
}
}
static Thread currentThread()
{
Thread javaThread = (Thread)cli.System.Threading.Thread.GetData(localDataStoreSlot);
if(javaThread == null)
// 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);
@ -491,7 +499,7 @@ final class VMThread
priority = Thread.MAX_PRIORITY;
break;
}
javaThread = new Thread(vmThread, nativeThread.get_Name(), priority, nativeThread.get_IsBackground());
Thread javaThread = new Thread(vmThread, nativeThread.get_Name(), priority, nativeThread.get_IsBackground());
if(!javaThread.daemon)
{
synchronized(countLock)
@ -502,11 +510,18 @@ final class VMThread
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 = group;
javaThread.group.addThread(javaThread);
InheritableThreadLocal.newChildThread(javaThread);
return javaThread;
}
static Thread currentThread()
{
Thread javaThread = (Thread)cli.System.Threading.Thread.GetData(localDataStoreSlot);
if(javaThread == null)
{
javaThread = newThread(ThreadGroup.root);
}
return javaThread;
}

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

@ -39,6 +39,7 @@ exception statement from your version. */
package java.lang.reflect;
import cli.System.Diagnostics.StackFrame;
import gnu.classpath.VMStackWalker;
/**
* The Constructor class represents a constructor of a class. It also allows
@ -259,7 +260,7 @@ public final class Constructor
InvocationTargetException
{
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);
if(Modifier.isAbstract(mods) || Modifier.isInterface(mods))
{

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

@ -39,6 +39,7 @@ exception statement from your version. */
package java.lang.reflect;
import cli.System.Diagnostics.StackFrame;
import gnu.classpath.VMStackWalker;
/**
* 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
{
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1));
checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
return GetValue(fieldCookie, o);
}
private static native Object GetValue(Object fieldCookie, Object o);
@ -262,7 +263,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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();
}
@ -287,7 +288,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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();
}
@ -310,7 +311,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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();
}
@ -335,7 +336,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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();
}
@ -360,7 +361,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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();
}
@ -385,7 +386,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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();
}
@ -410,7 +411,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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();
}
@ -436,7 +437,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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();
}
@ -489,17 +490,16 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
if(!isAccessible() && (!Modifier.isPublic(modifiers) || !classIsPublic))
checkAccess(modifiers, o, declaringClass, new StackFrame(1));
checkAccess(modifiers, o, declaringClass, VMStackWalker.getCallingClass());
SetValue(fieldCookie, o, 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.
Class actualClass = Modifier.isStatic(modifiers) || o == null ? declaringClass : o.getClass();
boolean declaringClassIsPublic = (Method.GetRealModifiers(declaringClass) & Modifier.PUBLIC) != 0;
Class caller = getClassFromFrame(frame);
if((!Modifier.isPublic(modifiers) || !declaringClassIsPublic) && declaringClass != caller)
{
// 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))
{
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 Class getClassFromFrame(StackFrame frame);
/**
* 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
{
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));
}
@ -565,7 +566,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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));
}
@ -590,7 +591,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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));
}
@ -615,7 +616,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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));
}
@ -640,7 +641,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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));
}
@ -665,7 +666,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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));
}
@ -690,7 +691,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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));
}
@ -715,7 +716,7 @@ public final class Field extends AccessibleObject implements Member
throws IllegalAccessException
{
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));
}
}

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

@ -39,6 +39,7 @@ exception statement from your version. */
package java.lang.reflect;
import cli.System.Diagnostics.StackFrame;
import gnu.classpath.VMStackWalker;
/**
* 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
{
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(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;
import gnu.classpath.RawData;
@ -12,9 +35,9 @@ class VMDirectByteBuffer
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)
@ -35,7 +58,7 @@ class VMDirectByteBuffer
static void get(RawData r, int index, byte[] dst, int offset, int length)
{
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)

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

@ -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" ?>
<!--
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
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">
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="(Ljava.lang.StringBuffer;)Ljava.lang.String;" />
</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">
<redirect class="java.lang.StringHelper" name="NewString" type="static" sig="([B)Ljava.lang.String;" />
</constructor>
@ -644,7 +655,7 @@
<method name="unbox_byte" sig="(Ljava.lang.Object;)B">
<body>
<ldarg_0 />
<unbox type="System.SByte, mscorlib" />
<unbox type="System.Byte, mscorlib" />
<ldind_i1 />
<ret />
</body>
@ -708,7 +719,7 @@
<method name="box_byte" sig="(B)Ljava.lang.Object;">
<body>
<ldarg_0 />
<box type="System.SByte, mscorlib" />
<box type="System.Byte, mscorlib" />
<ret />
</body>
</method>
@ -761,7 +772,7 @@
<ret />
</body>
</method>
<method name="box_ubyte" sig="(B)Lcli.System.Byte;">
<method name="box_sbyte" sig="(B)Lcli.System.SByte;">
<body>
<ldarg_0 />
<ret />
@ -785,7 +796,7 @@
<ret />
</body>
</method>
<method name="unbox_ubyte" sig="(Lcli.System.Byte;)B">
<method name="unbox_sbyte" sig="(Lcli.System.SByte;)B">
<body>
<ldarg_0 />
<ret />
@ -810,20 +821,6 @@
</body>
</method>
</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">
<method name="createField" sig="(Ljava.lang.Class;Ljava.lang.Object;)Ljava.lang.reflect.Field;">
<body>
@ -883,11 +880,8 @@
<method name="getDirectBufferAddress" sig="(Ljava.lang.Object;)Lcli.System.IntPtr;">
<body>
<ldarg_1 />
<castclass class="java.nio.ByteBuffer" />
<call class="java.nio.VMDirectByteBuffer" name="GetDirectBufferAddress" sig="(Ljava.nio.ByteBuffer;)Lcli.System.IntPtr;" />
<!-- LAME we need to unbox the return value -->
<unbox type="System.IntPtr, mscorlib" />
<ldobj type="System.IntPtr, mscorlib" />
<castclass class="java.nio.Buffer" />
<call class="java.nio.VMDirectByteBuffer" name="GetDirectBufferAddress" sig="(Ljava.nio.Buffer;)Lcli.System.IntPtr;" />
<ret />
</body>
</method>
@ -909,7 +903,7 @@
</body>
</method>
</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;">
<body>
<ldarg_0 />
@ -938,7 +932,7 @@
<ldarg_0 />
<ldfld class="java.nio.Buffer" name="pos" sig="I" />
<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 />
<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
// 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

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

@ -49,7 +49,7 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Revision and Build Numbers
// 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

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

@ -49,7 +49,7 @@ using System.Runtime.CompilerServices;
// You can specify all the values or you can default the Revision and Build Numbers
// 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

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

@ -724,9 +724,9 @@ class ClassFileWriter
if(constantValue != null)
{
ushort constantValueIndex;
if(constantValue is sbyte)
if(constantValue is byte)
{
constantValueIndex = AddInt((sbyte)constantValue);
constantValueIndex = AddInt((sbyte)(byte)constantValue);
}
else if(constantValue is bool)
{
@ -744,18 +744,10 @@ class ClassFileWriter
{
constantValueIndex = AddInt((int)constantValue);
}
else if(constantValue is uint)
{
constantValueIndex = AddInt((int)(uint)constantValue);
}
else if(constantValue is long)
{
constantValueIndex = AddLong((long)constantValue);
}
else if(constantValue is ulong)
{
constantValueIndex = AddLong((long)(ulong)constantValue);
}
else if(constantValue is float)
{
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
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.Collections;
using ICSharpCode.SharpZipLib.Zip;
using java.lang;
using java.lang.reflect;
using IKVM.Attributes;
using IKVM.Internal;
@ -79,6 +77,7 @@ public class NetExp
{
assembly = Assembly.LoadWithPartialName(args[0]);
}
int rc = 0;
if(assembly == null)
{
Console.Error.WriteLine("Error: Assembly \"{0}\" not found", args[0]);
@ -94,12 +93,13 @@ public class NetExp
catch(System.Exception x)
{
java.lang.Throwable.instancehelper_printStackTrace(IKVM.Runtime.Util.MapException(x));
rc = 1;
}
zipFile.Close();
}
// FXBUG if we run a static initializer that starts a thread, we would never end,
// so we force an exit here
Environment.Exit(0);
Environment.Exit(rc);
}
private static void WriteClass(string name, ClassFileWriter c)
@ -114,12 +114,12 @@ public class NetExp
{
if(t.IsPublic)
{
Class c;
java.lang.Class c;
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
continue;
@ -139,7 +139,7 @@ public class NetExp
Hashtable todo = privateClasses;
privateClasses = new Hashtable();
keepGoing = false;
foreach(Class c in todo.Values)
foreach(java.lang.Class c in todo.Values)
{
if(!done.ContainsKey(c.getName()))
{
@ -151,7 +151,7 @@ public class NetExp
} 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 super = null;
@ -159,7 +159,7 @@ public class NetExp
{
super = c.getSuperclass().getName().Replace('.', '/');
// 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();
}
@ -196,15 +196,15 @@ public class NetExp
}
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++)
{
if(Modifier.isPublic(interfaces[i].getModifiers()))
if(java.lang.reflect.Modifier.isPublic(interfaces[i].getModifiers()))
{
f.AddInterface(interfaces[i].getName().Replace('.', '/'));
}
}
Class[] innerClasses = c.getDeclaredClasses();
java.lang.Class[] innerClasses = c.getDeclaredClasses();
for(int i = 0; i < innerClasses.Length; i++)
{
Modifiers mods = (Modifiers)innerClasses[i].getModifiers();
@ -220,7 +220,7 @@ public class NetExp
ProcessClass(assemblyName, innerClasses[i], c);
}
}
Constructor[] constructors = c.getDeclaredConstructors();
java.lang.reflect.Constructor[] constructors = c.getDeclaredConstructors();
for(int i = 0; i < constructors.Length; i++)
{
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++)
{
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++)
{
Modifiers mods = (Modifiers)fields[i].getModifiers();
@ -340,12 +340,12 @@ public class NetExp
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)
{
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?
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();
sb.Append('(');
@ -367,7 +367,7 @@ public class NetExp
return sb.ToString();
}
private static string ClassToSig(Class c)
private static string ClassToSig(java.lang.Class c)
{
if(c.isPrimitive())
{

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

@ -8,7 +8,7 @@
<property name="REFERENCE_API_NAME" value="JDK-1.5" />
-->
<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">
<call target="status" />

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

@ -23,12 +23,9 @@
*/
.assembly JVM
{
.ver 0:10:0:1
.ver 0:11:0:0
}
.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)
{

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

@ -3,6 +3,9 @@
<target name="JVM">
<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="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>
</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
// 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

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

@ -176,7 +176,7 @@ namespace IKVM.Runtime
}
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();
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)
{
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]

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

@ -1116,8 +1116,20 @@ sealed class ClassFile
{
field = wrapper.GetFieldWrapper(Name, Signature);
if(field != null)
{
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);
break;
case "B":
constantValue = (sbyte)classFile.GetConstantPoolConstantInteger(index);
constantValue = (byte)classFile.GetConstantPoolConstantInteger(index);
break;
case "C":
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
warranty. In no event will the authors be held liable for any damages
@ -504,8 +504,10 @@ class ClassLoaderWrapper
// for .NET to handle.
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;
Debug.Assert(!elementType.IsArray);
TypeWrapper wrapper;
lock(types.SyncRoot)
{
@ -809,7 +811,7 @@ class ClassLoaderWrapper
Type[] types = new Type[wrappers.Length];
for(int i = 0; i < wrappers.Length; i++)
{
types[i] = wrappers[i].TypeAsParameterType;
types[i] = wrappers[i].TypeAsSignatureType;
}
return types;
}
@ -986,11 +988,6 @@ class ClassLoaderWrapper
rank++;
elem = elem.GetElementType();
}
// HACK BYTE[]
//if(elem == typeof(byte))
//{
// elem = typeof(sbyte);
//}
wrapper = GetWrapperFromType(elem);
return wrapper.MakeArrayType(rank);
}

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

@ -79,13 +79,19 @@ namespace IKVM.Runtime
public unsafe sealed class JNI
{
internal static bool jvmCreated;
internal static bool jvmDestroyed;
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)
{
JavaVMInitArgs* pInitArgs = (JavaVMInitArgs*)args;
// 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;
}
@ -377,43 +383,11 @@ namespace IKVM.Runtime
[DllImport("ikvm-native")]
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();
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)
{
IntPtr p = ikvm_LoadLibrary(filename);
@ -444,7 +418,7 @@ namespace IKVM.Runtime
ClassLoaderWrapper prevLoader = f.Enter(loader);
int version = ikvm_CallOnLoad(onload, JavaVM.pJavaVM, null);
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);
}
@ -922,9 +896,14 @@ namespace IKVM.Runtime
internal static jint DestroyJavaVM(JavaVM* pJVM)
{
JVM.Library.jniWaitUntilLastThread();
if(JNI.jvmDestroyed)
{
return JNIEnv.JNI_ERR;
}
JNI.jvmDestroyed = true;
JVM.Library.jniWaitUntilLastThread();
return JNIEnv.JNI_OK;
}
internal static jint AttachCurrentThread(JavaVM* pJVM, void **penv, void *args)
{
@ -935,7 +914,7 @@ namespace IKVM.Runtime
{
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;
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,
// 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.
System.Threading.Thread.CurrentThread.IsBackground = asDaemon;
if(pAttachArgs != null)
{
if(pAttachArgs->name != null && System.Threading.Thread.CurrentThread.Name == null)
{
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
object threadGroup = p->UnwrapRef(pAttachArgs->group);
if(threadGroup != null)
{
// TODO instead of using a thread data slot to communicate the thread group, we should probably use
// another mechanism, this is probably a security issue.
System.Threading.Thread.SetData(System.Threading.Thread.GetNamedDataSlot("ikvm-thread-group"), threadGroup);
JVM.Library.setThreadGroup(threadGroup);
}
}
System.Threading.Thread.CurrentThread.IsBackground = asDaemon;
*penv = JNIEnv.CreateJNIEnv();
return JNIEnv.JNI_OK;
}
@ -974,7 +958,8 @@ namespace IKVM.Runtime
{
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.
JNIEnv.FreeJNIEnv();
@ -982,14 +967,9 @@ namespace IKVM.Runtime
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)
{
if(IsSupportedJniVersion(version))
if(JNI.IsSupportedJniVersion(version))
{
JNIEnv* p = TlsHack.pJNIEnv;
if(p != null)
@ -1013,6 +993,8 @@ namespace IKVM.Runtime
[StructLayout(LayoutKind.Sequential)]
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_BUCKET_SIZE = (1 << LOCAL_REF_SHIFT);
internal const int LOCAL_REF_MASK = (LOCAL_REF_BUCKET_SIZE - 1);
@ -1255,23 +1237,38 @@ namespace IKVM.Runtime
return ClassLoaderWrapper.GetSystemClassLoader();
}
internal static jclass FindClass(JNIEnv* pEnv, byte* name)
internal static jclass FindClass(JNIEnv* pEnv, byte* pszName)
{
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();
// spec doesn't say it, but Sun runs the static initializer
wrapper.RunClassInit();
return pEnv->MakeLocalRef(wrapper.ClassObject);
}
catch(RetargetableJavaException x)
{
SetPendingException(pEnv, x.ToJava());
return IntPtr.Zero;
}
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);
return IntPtr.Zero;
}
@ -1415,8 +1412,15 @@ namespace IKVM.Runtime
localRefs[pEnv->localRefSlot - 1] = null;
if(localRefs[pEnv->localRefSlot] == null)
{
// we can't use capacity, because the array length must be a power of two
localRefs[pEnv->localRefSlot] = new object[LOCAL_REF_BUCKET_SIZE];
// we can't use capacity directly, because the array length must be a power of two
// 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;
}
@ -1600,7 +1604,7 @@ namespace IKVM.Runtime
}
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;
}
@ -1621,6 +1625,8 @@ namespace IKVM.Runtime
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));
TypeWrapper w1 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
TypeWrapper w2 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(objClass);
@ -1680,7 +1686,7 @@ namespace IKVM.Runtime
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
return (jbyte)(sbyte)o;
return (jbyte)(byte)o;
}
return 0;
}
@ -1770,7 +1776,7 @@ namespace IKVM.Runtime
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
return (jbyte)(sbyte)o;
return (jbyte)(byte)o;
}
return 0;
}
@ -1851,7 +1857,6 @@ namespace IKVM.Runtime
{
if(fw.IsStatic == isstatic)
{
// TODO fw.Link()
return fw.Cookie;
}
}
@ -1911,7 +1916,7 @@ namespace IKVM.Runtime
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)
@ -1956,7 +1961,7 @@ namespace IKVM.Runtime
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)
@ -2014,7 +2019,7 @@ namespace IKVM.Runtime
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
return (jbyte)(sbyte)o;
return (jbyte)(byte)o;
}
return 0;
}
@ -2101,7 +2106,7 @@ namespace IKVM.Runtime
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)
@ -2146,7 +2151,7 @@ namespace IKVM.Runtime
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)
@ -2328,7 +2333,7 @@ namespace IKVM.Runtime
{
try
{
return pEnv->MakeLocalRef(new sbyte[len]);
return pEnv->MakeLocalRef(new byte[len]);
}
catch(Exception x)
{
@ -2432,7 +2437,7 @@ namespace IKVM.Runtime
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);
for(int i = 0; i < b.Length; i++)
{
@ -2537,10 +2542,10 @@ namespace IKVM.Runtime
{
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++)
{
b[i] = (sbyte)elems[i];
b[i] = (byte)elems[i];
}
}
if(mode == 0 || mode == JNI_ABORT)
@ -2648,8 +2653,8 @@ namespace IKVM.Runtime
{
try
{
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array);
sbyte* p = (sbyte*)(void*)buf;
byte[] b = (byte[])pEnv->UnwrapRef(array);
byte* p = (byte*)(void*)buf;
for(int i = 0; i < len; i++)
{
*p++ = b[start + i];
@ -2760,8 +2765,8 @@ namespace IKVM.Runtime
{
try
{
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array);
sbyte* p = (sbyte*)(void*)buf;
byte[] b = (byte[])pEnv->UnwrapRef(array);
byte* p = (byte*)(void*)buf;
for(int i = 0; i < len; i++)
{
b[start + i] = *p++;
@ -3023,19 +3028,19 @@ namespace IKVM.Runtime
private static int GetPrimitiveArrayElementSize(Array ar)
{
Type type = ar.GetType().GetElementType();
if(type == typeof(sbyte) || type == typeof(bool))
if(type == PrimitiveTypeWrapper.BYTE.TypeAsArrayType || type == PrimitiveTypeWrapper.BOOLEAN.TypeAsArrayType)
{
return 1;
}
else if(type == typeof(short) || type == typeof(char))
else if(type == PrimitiveTypeWrapper.SHORT.TypeAsArrayType || type == PrimitiveTypeWrapper.CHAR.TypeAsArrayType)
{
return 2;
}
else if(type == typeof(int) || type == typeof(float))
else if(type == PrimitiveTypeWrapper.INT.TypeAsArrayType || type == PrimitiveTypeWrapper.FLOAT.TypeAsArrayType)
{
return 4;
}
else if(type == typeof(long) || type == typeof(double))
else if(type == PrimitiveTypeWrapper.LONG.TypeAsArrayType || type == PrimitiveTypeWrapper.DOUBLE.TypeAsArrayType)
{
return 8;
}
@ -3049,6 +3054,7 @@ namespace IKVM.Runtime
internal static IntPtr GetPrimitiveArrayCritical(JNIEnv* pEnv, IntPtr array, IntPtr isCopy)
{
Array ar = (Array)pEnv->UnwrapRef(array);
// TODO not 64-bit safe (len can overflow)
int len = ar.Length * GetPrimitiveArrayElementSize(ar);
GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned);
try
@ -3078,6 +3084,7 @@ namespace IKVM.Runtime
if(mode == 0 || mode == JNI_COMMIT)
{
Array ar = (Array)pEnv->UnwrapRef(array);
// TODO not 64-bit safe (len can overflow)
int len = ar.Length * GetPrimitiveArrayElementSize(ar);
GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned);
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;
}

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

@ -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
warranty. In no event will the authors be held liable for any damages
@ -209,7 +209,7 @@ abstract class MethodWrapper : MemberWrapper
{
if(ghostMethod == null)
{
ghostMethod = DeclaringType.TypeAsParameterType.GetMethod(this.Name, this.GetParametersForDefineMethod());
ghostMethod = DeclaringType.TypeAsSignatureType.GetMethod(this.Name, this.GetParametersForDefineMethod());
if(ghostMethod == null)
{
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)
{
object wrapper = Activator.CreateInstance(DeclaringType.TypeAsParameterType);
object wrapper = Activator.CreateInstance(DeclaringType.TypeAsSignatureType);
DeclaringType.GhostRefField.SetValue(wrapper, obj);
ResolveGhostMethod();
@ -245,7 +245,7 @@ abstract class MethodWrapper : MemberWrapper
Type[] types = new Type[parameterTypes.Length];
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);
}
@ -383,7 +383,7 @@ abstract class MethodWrapper : MemberWrapper
{
get
{
return ReturnType.TypeAsParameterType;
return ReturnType.TypeAsSignatureType;
}
}
@ -393,7 +393,7 @@ abstract class MethodWrapper : MemberWrapper
Type[] temp = new Type[wrappers.Length];
for(int i = 0; i < wrappers.Length; i++)
{
temp[i] = wrappers[i].TypeAsParameterType;
temp[i] = wrappers[i].TypeAsSignatureType;
}
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);
try
@ -683,6 +688,8 @@ abstract class MethodWrapper : MemberWrapper
AssemblyName name = new AssemblyName();
name.Name = "NonvirtualInvoker";
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)
{
module = ab.DefineDynamicModule("NonvirtualInvoker", "NonvirtualInvoker.dll");
@ -747,7 +754,10 @@ abstract class MethodWrapper : MemberWrapper
}
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)
{
@ -780,7 +790,7 @@ abstract class MethodWrapper : MemberWrapper
{
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]);
args[i + 1] = v;
}
@ -798,7 +808,7 @@ abstract class MethodWrapper : MemberWrapper
{
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]);
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)
{
AssertLinked();
PreEmit(ilgen);
CallImpl(ilgen);
PostEmit(ilgen);
}
protected virtual void CallImpl(ILGenerator ilgen)
@ -883,13 +873,13 @@ class SmartMethodWrapper : MethodWrapper
if(DeclaringType.IsNonPrimitiveValueType)
{
// callvirt isn't allowed on a value type
// TODO we need to check for a null reference
CallImpl(ilgen);
}
else
{
CallvirtImpl(ilgen);
}
PostEmit(ilgen);
}
protected virtual void CallvirtImpl(ILGenerator ilgen)
@ -1281,29 +1271,6 @@ sealed class SimpleFieldWrapper : FieldWrapper
}
protected override void EmitGetImpl(ILGenerator ilgen)
{
if(FieldTypeWrapper.IsGhost)
{
FieldInfo fi = GetField();
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(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
{
@ -1314,59 +1281,23 @@ sealed class SimpleFieldWrapper : FieldWrapper
ilgen.Emit(OpCodes.Volatile);
}
ilgen.Emit(IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld, GetField());
if(!FieldTypeWrapper.IsUnloadable && FieldTypeWrapper.IsNonPrimitiveValueType)
{
FieldTypeWrapper.EmitBox(ilgen);
}
}
}
protected override void EmitSetImpl(ILGenerator ilgen)
{
if(FieldTypeWrapper.IsGhost)
{
FieldInfo fi = GetField();
LocalBuilder temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
ilgen.Emit(OpCodes.Stloc, temp);
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);
if(IsVolatile)
{
ilgen.Emit(OpCodes.Volatile);
}
ilgen.Emit(OpCodes.Stfld, FieldTypeWrapper.GhostRefField);
}
else
{
if(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
{
FieldInfo fi = GetField();
LocalBuilder temp = ilgen.DeclareLocal(FieldTypeWrapper.TypeAsLocalOrStackType);
LocalBuilder temp = ilgen.DeclareLocal(fi.FieldType);
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)
{
Debug.Assert(IsVolatile);
Debug.Assert(fieldType == PrimitiveTypeWrapper.DOUBLE || fieldType == PrimitiveTypeWrapper.LONG);
Debug.Assert(sig == "J" || sig == "D");
}
protected override void EmitGetImpl(ILGenerator ilgen)
@ -1460,90 +1391,32 @@ sealed class GetterFieldWrapper : FieldWrapper
protected override void EmitGetImpl(ILGenerator ilgen)
{
if(IsStatic)
{
ilgen.Emit(OpCodes.Call, getter);
}
else
{
if(DeclaringType.IsNonPrimitiveValueType)
if(!IsStatic && DeclaringType.IsNonPrimitiveValueType)
{
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
ilgen.Emit(OpCodes.Call, getter);
}
else
{
// 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(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)
{
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);
if(DeclaringType.IsNonPrimitiveValueType)
{
ilgen.Emit(OpCodes.Unbox, DeclaringType.TypeAsTBD);
}
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);
}
}
}
}
// NOTE this type is only used for remapped fields, dynamically compiled classes are always finished before we
// allow reflection (so we can look at the underlying field in that case)
@ -1569,6 +1442,8 @@ sealed class ConstantFieldWrapper : FieldWrapper
}
else if(constant is int ||
constant is short ||
constant is ushort ||
constant is byte ||
constant is sbyte ||
constant is char ||
constant is bool)
@ -1591,25 +1466,13 @@ sealed class ConstantFieldWrapper : FieldWrapper
{
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)
{
ilgen.Emit(OpCodes.Ldc_I4, unchecked((int)((IConvertible)constant).ToUInt32(null)));
ilgen.Emit(OpCodes.Box, typeof(uint));
}
else if(constant is ulong)
{
ilgen.Emit(OpCodes.Ldc_I8, unchecked((long)(ulong)constant));
ilgen.Emit(OpCodes.Box, typeof(ulong));
}
else if(constant is Enum)
{
@ -1617,12 +1480,10 @@ sealed class ConstantFieldWrapper : FieldWrapper
if(val is long)
{
ilgen.Emit(OpCodes.Ldc_I8, (long)constant);
ilgen.Emit(OpCodes.Box, constant.GetType());
}
else
{
ilgen.Emit(OpCodes.Ldc_I4, ((IConvertible)constant).ToInt32(null));
ilgen.Emit(OpCodes.Box, constant.GetType());
}
}
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
// 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);
}

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

@ -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
warranty. In no event will the authors be held liable for any damages
@ -472,7 +472,7 @@ abstract class TypeWrapper
this.name = name;
this.baseWrapper = baseWrapper;
this.classLoader = classLoader;
if(JVM.IsStaticCompiler)
if(IsUnloadable || IsVerifierType || JVM.IsStaticCompiler)
{
this.classObject = null;
}
@ -486,7 +486,7 @@ abstract class TypeWrapper
{
get
{
Debug.Assert(!IsUnloadable);
Debug.Assert(!IsUnloadable && !IsVerifierType);
return classObject;
}
}
@ -902,15 +902,7 @@ abstract class TypeWrapper
}
}
internal Type TypeAsFieldType
{
get
{
return TypeAsParameterType;
}
}
internal Type TypeAsParameterType
internal Type TypeAsSignatureType
{
get
{
@ -991,13 +983,7 @@ abstract class TypeWrapper
}
return Type.GetType(type, true);
}
Type t = TypeAsTBD;
// HACK BYTE[]
//if(t == typeof(sbyte))
//{
// return typeof(byte);
//}
return t;
return TypeAsTBD;
}
}
@ -1337,9 +1323,31 @@ abstract class TypeWrapper
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
internal void EmitConvStackToParameterType(ILGenerator ilgen, TypeWrapper sourceType)
internal void EmitConvStackTypeToSignatureType(ILGenerator ilgen, TypeWrapper sourceType)
{
if(!IsUnloadable)
{
@ -1347,12 +1355,12 @@ abstract class TypeWrapper
{
LocalBuilder local1 = ilgen.DeclareLocal(TypeAsLocalOrStackType);
ilgen.Emit(OpCodes.Stloc, local1);
LocalBuilder local2 = ilgen.DeclareLocal(TypeAsParameterType);
LocalBuilder local2 = ilgen.DeclareLocal(TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local2);
ilgen.Emit(OpCodes.Ldloc, local1);
ilgen.Emit(OpCodes.Stfld, GhostRefField);
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
// 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)
{
if(IsGhost)
@ -1599,7 +1588,7 @@ class UnloadableTypeWrapper : 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 DOUBLE = new PrimitiveTypeWrapper(typeof(double), "D");
internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper(typeof(float), "F");
@ -1675,6 +1664,11 @@ class PrimitiveTypeWrapper : TypeWrapper
internal override void Finish(bool forDebugSave)
{
}
public override string ToString()
{
return "PrimitiveTypeWrapper[" + sigName + "]";
}
}
class BakedTypeCleanupHack
@ -2278,6 +2272,8 @@ sealed class DynamicTypeWrapper : TypeWrapper
{
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();
}
// 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++)
{
if(caller[i].TypeAsParameterType == typeof(sbyte[]) && callee[i].TypeAsParameterType == typeof(byte[]))
{
// special case for byte array cheating...
}
else if(!caller[i].IsAssignableTo(callee[i]))
if(!caller[i].IsAssignableTo(callee[i]))
{
return false;
}
@ -2629,7 +2621,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
ClassFile.Field fld = classFile.Fields[GetFieldIndex(fw)];
string fieldName = fld.Name;
TypeWrapper typeWrapper = fw.FieldTypeWrapper;
Type type = typeWrapper.TypeAsFieldType;
Type type = typeWrapper.TypeAsSignatureType;
bool setNameSig = typeWrapper.IsUnloadable || typeWrapper.IsGhostArray;
if(setNameSig)
{
@ -2905,15 +2897,15 @@ sealed class DynamicTypeWrapper : TypeWrapper
TypeWrapper[] implementers = GetGhostImplementers(wrapper);
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);
ilgen = mb.GetILGenerator();
local = ilgen.DeclareLocal(wrapper.TypeAsParameterType);
local = ilgen.DeclareLocal(wrapper.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Stfld, wrapper.GhostRefField);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldobj, wrapper.TypeAsParameterType);
ilgen.Emit(OpCodes.Ldobj, wrapper.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ret);
}
// Implement the "IsInstance" method
@ -3005,12 +2997,12 @@ sealed class DynamicTypeWrapper : TypeWrapper
ilgen.Emit(OpCodes.Castclass, wrapper.TypeAsBaseType);
ilgen.Emit(OpCodes.Pop);
ilgen.MarkLabel(end);
local = ilgen.DeclareLocal(wrapper.TypeAsParameterType);
local = ilgen.DeclareLocal(wrapper.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Stfld, wrapper.ghostRefField);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldobj, wrapper.TypeAsParameterType);
ilgen.Emit(OpCodes.Ldobj, wrapper.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ret);
// Add "ToObject" methods
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
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);
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.Ldarg_0);
ilgen.Emit(OpCodes.Stfld, interfaces[i].GhostRefField);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldobj, interfaces[i].TypeAsParameterType);
ilgen.Emit(OpCodes.Ldobj, interfaces[i].TypeAsSignatureType);
ilgen.Emit(OpCodes.Ret);
}
interfaces[i].ImplementInterfaceMethodStubs(typeBuilder, wrapper, doneSet);
@ -3321,13 +3313,13 @@ sealed class DynamicTypeWrapper : TypeWrapper
if(f.ConstantValue != null)
{
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);
}
else
{
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)
{
ilgenClinit = tbFields.DefineTypeInitializer().GetILGenerator();
@ -3406,14 +3398,14 @@ sealed class DynamicTypeWrapper : TypeWrapper
Type[] argTypes = new Type[args.Length + instance + 1];
if(instance != 0)
{
argTypes[0] = wrapper.TypeAsParameterType;
argTypes[0] = wrapper.TypeAsSignatureType;
}
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);
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);
for(int i = 0; i < argTypes.Length - 1; i++)
{
@ -3507,7 +3499,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
ilGenerator.Emit(OpCodes.Stloc, jnienv);
Label tryBlock = ilGenerator.BeginExceptionBlock();
TypeWrapper retTypeWrapper = mw.ReturnType;
if(!retTypeWrapper.IsPrimitive)
if(!retTypeWrapper.IsUnloadable && !retTypeWrapper.IsPrimitive)
{
// this one is for use after we return from "calli"
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
@ -3518,7 +3510,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
modargs[1] = typeof(IntPtr);
for(int i = 0; i < args.Length; i++)
{
modargs[i + 2] = args[i].TypeAsParameterType;
modargs[i + 2] = args[i].TypeAsSignatureType;
}
int add = 0;
if(!m.IsStatic)
@ -3548,11 +3540,20 @@ sealed class DynamicTypeWrapper : TypeWrapper
if(!args[j].IsPrimitive)
{
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
if(args[j].IsNonPrimitiveValueType)
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
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);
modargs[j + 2] = typeof(IntPtr);
}
@ -3562,7 +3563,7 @@ sealed class DynamicTypeWrapper : TypeWrapper
}
}
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;
if(retTypeWrapper != PrimitiveTypeWrapper.VOID)
{
@ -3573,12 +3574,22 @@ sealed class DynamicTypeWrapper : TypeWrapper
{
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);
}
}
retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsParameterType);
retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Stloc, retValue);
}
ilGenerator.BeginCatchBlock(typeof(object));
@ -5069,7 +5080,7 @@ sealed class DotNetTypeWrapper : TypeWrapper
{
modifiers |= Modifiers.Final;
}
if(type.IsAbstract)
else if(type.IsAbstract) // we can't be abstract if we're final
{
modifiers |= Modifiers.Abstract;
}
@ -5374,8 +5385,9 @@ sealed class DotNetTypeWrapper : TypeWrapper
internal override void EmitCall(ILGenerator ilgen)
{
// NOTE we don't support custom boxing rules for enums
ilgen.Emit(OpCodes.Box, ((DotNetTypeWrapper)DeclaringType).type);
// We don't actually need to do anything here!
// 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)
@ -5432,13 +5444,13 @@ sealed class DotNetTypeWrapper : TypeWrapper
}
// 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)
{
Type underlyingType = Enum.GetUnderlyingType(obj.GetType());
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))
{
@ -5512,9 +5524,9 @@ sealed class DotNetTypeWrapper : TypeWrapper
if(type.IsEnum)
{
Type underlyingType = Enum.GetUnderlyingType(type);
if(underlyingType == typeof(byte))
if(underlyingType == typeof(sbyte))
{
underlyingType = typeof(sbyte);
underlyingType = typeof(byte);
}
else if(underlyingType == typeof(ushort))
{
@ -5631,6 +5643,7 @@ sealed class DotNetTypeWrapper : TypeWrapper
// (otherwise the type appears abstract while it isn't)
if(!type.IsAbstract)
{
Hashtable clash = null;
Type[] interfaces = type.GetInterfaces();
for(int i = 0; i < interfaces.Length; i++)
{
@ -5653,7 +5666,17 @@ sealed class DotNetTypeWrapper : TypeWrapper
continue;
}
}
// TODO handle name/signature clash
if(clash == null)
{
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));
}
}
@ -5661,6 +5684,7 @@ sealed class DotNetTypeWrapper : TypeWrapper
}
}
}
}
// for non-final remapped types, we need to add all the virtual methods in our alter ego (which
// appears as our base class) and make them final (to prevent Java code from overriding these

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

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

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

@ -164,6 +164,13 @@ namespace IKVM.NativeCode.java
throw JavaException.IllegalArgumentException("primitive wrapper null");
}
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
{
@ -221,16 +228,6 @@ namespace IKVM.NativeCode.java
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)
{
Profiler.Enter("Field.GetValue");
@ -272,6 +269,13 @@ namespace IKVM.NativeCode.java
if(wrapper.FieldTypeWrapper.IsPrimitive)
{
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>,
// because .NET reflection doesn't
@ -291,9 +295,9 @@ namespace IKVM.NativeCode.java
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 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");
}
}
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
@ -1162,7 +1138,7 @@ namespace IKVM.NativeCode.java
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);
}
@ -1185,7 +1161,21 @@ namespace IKVM.NativeCode.java
// 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
// 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)
@ -1223,9 +1213,9 @@ namespace IKVM.NativeCode.java
{
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()
@ -1234,23 +1224,17 @@ namespace IKVM.NativeCode.java
return NetSystem.Net.Dns.GetHostName();
}
public static sbyte[][] getHostByName(string name)
public static byte[][] getHostByName(string name)
{
// TODO error handling
try
{
NetSystem.Net.IPHostEntry he = NetSystem.Net.Dns.GetHostByName(name);
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++)
{
byte[] address = 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;
list[i] = addresses[i].GetAddressBytes();
}
return list;
}
@ -1392,6 +1376,31 @@ namespace IKVM.NativeCode.gnu.classpath
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
@ -1401,11 +1410,11 @@ namespace gnu.classpath
public unsafe sealed class RawData
{
[HideFromJava]
private sbyte* pb;
private byte* pb;
public RawData(IntPtr p)
{
this.pb = (sbyte*)p;
this.pb = (byte*)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
// demand to these dangerous methods.
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public sbyte ReadByte(int index)
public byte ReadByte(int index)
{
return pb[index];
}
[SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
public void WriteByte(int index, sbyte b)
public void WriteByte(int index, byte b)
{
pb[index] = b;
}
@ -1467,6 +1476,7 @@ namespace ikvm.@internal
void jniWaitUntilLastThread();
void jniDetach();
void setThreadGroup(object group);
object newConstructor(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
warranty. In no event will the authors be held liable for any damages
@ -175,8 +175,9 @@ class Compiler
{
tw = args[arg - 1];
}
if(v.type != VerifierTypeWrapper.UninitializedThis &&
(v.type != tw || tw.TypeAsLocalOrStackType != tw.TypeAsParameterType))
if(!tw.IsUnloadable &&
v.type != VerifierTypeWrapper.UninitializedThis &&
(v.type != tw || tw.TypeAsLocalOrStackType != tw.TypeAsSignatureType))
{
v.builder = ilGenerator.DeclareLocal(v.type.TypeAsLocalOrStackType);
if(JVM.Debug && v.name != null)
@ -185,7 +186,7 @@ class Compiler
}
v.isArg = false;
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)arg);
v.type.EmitConvParameterToStackType(ilGenerator);
tw.EmitConvSignatureTypeToStackType(ilGenerator);
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
CastInterfaceArgs(method, cpi.GetArgTypes(), i, false, false);
method.EmitCall(ilGenerator);
method.ReturnType.EmitConvSignatureTypeToStackType(ilGenerator);
break;
}
case NormalizedByteCode.__invokevirtual:
@ -1614,6 +1616,7 @@ class Compiler
{
method.EmitCallvirt(ilGenerator);
}
method.ReturnType.EmitConvSignatureTypeToStackType(ilGenerator);
}
break;
}
@ -1631,12 +1634,12 @@ class Compiler
if(instr.NormalizedOpCode != NormalizedByteCode.__return)
{
TypeWrapper retTypeWrapper = mw.ReturnType;
retTypeWrapper.EmitConvStackToParameterType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0));
retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0));
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);
}
Label label = ilGenerator.DefineLabel();
@ -1660,14 +1663,14 @@ class Compiler
else
{
TypeWrapper retTypeWrapper = mw.ReturnType;
retTypeWrapper.EmitConvStackToParameterType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0));
retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0));
if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable)
{
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsParameterType);
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsSignatureType);
}
if(stackHeight != 1)
{
LocalBuilder local = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsParameterType);
LocalBuilder local = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Stloc, local);
ilGenerator.Emit(OpCodes.Leave_S, (byte)0);
ilGenerator.Emit(OpCodes.Ldloc, local);
@ -2809,7 +2812,7 @@ class Compiler
}
else
{
LocalBuilder local = ilGenerator.DeclareLocal(args[i].TypeAsParameterType);
LocalBuilder local = ilGenerator.DeclareLocal(args[i].TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Ldloca, local);
dh.Load(i);
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
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)
{
ilGenerator.Emit(OpCodes.Castclass, args[i].TypeAsParameterType);
ilGenerator.Emit(OpCodes.Castclass, args[i].TypeAsSignatureType);
}
}
}
@ -2925,16 +2928,14 @@ class Compiler
if(!write)
{
field.EmitGet(ilGenerator);
field.FieldTypeWrapper.EmitConvSignatureTypeToStackType(ilGenerator);
return;
}
else
{
TypeWrapper tw = field.FieldTypeWrapper;
TypeWrapper val = ma.GetRawStackTypeWrapper(i, 0);
if(!tw.IsUnloadable && (val.IsUnloadable || (tw.IsInterfaceOrInterfaceArray && !tw.IsGhost && !val.IsAssignableTo(tw))))
{
ilGenerator.Emit(OpCodes.Castclass, tw.TypeAsTBD);
}
tw.EmitConvStackTypeToSignatureType(ilGenerator, val);
field.EmitSet(ilGenerator);
return;
}
@ -2972,6 +2973,10 @@ class Compiler
// 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.Ldobj, typeWrapper.TypeAsTBD);
if(typeWrapper == PrimitiveTypeWrapper.BYTE)
{
ilgen.Emit(OpCodes.Conv_I1);
}
}
else
{
@ -2989,7 +2994,7 @@ class Compiler
private 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.wrapper = wrapper;

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

@ -145,9 +145,9 @@ namespace IKVM.Internal.MapXml
}
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]);
}
for(int j = 0; j < temps.Length; j++)
@ -672,8 +672,7 @@ namespace IKVM.Internal.MapXml
{
FieldWrapper fw = ClassLoaderWrapper.LoadClassCritical(Class).GetFieldWrapper(Name, Sig);
fw.Link();
// we don't use fw.EmitGet because we don't want automatic boxing and whatever
ilgen.Emit(OpCodes.Ldfld, fw.GetField());
fw.EmitGet(ilgen);
}
}

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

@ -31,6 +31,7 @@ using System.Collections;
using System.Xml;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Text;
using IKVM.Attributes;
using IKVM.Runtime;
@ -99,7 +100,7 @@ namespace IKVM.Runtime
{
ArrayList list = new ArrayList();
string cmdline = Environment.CommandLine;
System.Text.StringBuilder sb = new System.Text.StringBuilder();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < cmdline.Length;)
{
bool quoted = cmdline[i] == '"';
@ -406,7 +407,7 @@ namespace IKVM.Internal
// 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 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)
{
if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+.()$#@~=&{}[]0123456789`".IndexOf(c) != -1)
@ -1121,7 +1122,7 @@ namespace IKVM.Internal
typeWrapper.helperTypeBuilder = typeWrapper.typeBuilder.DefineNestedType("__Helper", TypeAttributes.NestedPublic | TypeAttributes.Class);
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();
foreach(IKVM.Internal.MapXml.Class c in specialCases)
{
@ -1156,7 +1157,7 @@ namespace IKVM.Internal
{
MethodBuilder mbCore = null;
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)
{
@ -1276,7 +1277,7 @@ namespace IKVM.Internal
{
if(instr is IKVM.Internal.MapXml.Ret)
{
this.ReturnType.EmitConvStackToParameterType(ilgen, null);
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
}
instr.Generate(context, ilgen);
}
@ -1309,7 +1310,7 @@ namespace IKVM.Internal
}
ilgen.Emit(OpCodes.Call, baseMethod);
}
this.ReturnType.EmitConvStackToParameterType(ilgen, null);
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
ilgen.Emit(OpCodes.Ret);
}
ilgen.EmitLineNumberTable(mbCore);
@ -1344,7 +1345,7 @@ namespace IKVM.Internal
ilgen.Emit(OpCodes.Ldarg, (short)(i + 1));
}
ilgen.Emit(OpCodes.Callvirt, mbCore);
this.ReturnType.EmitConvStackToParameterType(ilgen, null);
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
ilgen.Emit(OpCodes.Ret);
ilgen.MarkLabel(skip);
ilgen.Emit(OpCodes.Pop);
@ -1370,7 +1371,7 @@ namespace IKVM.Internal
}
mw.Link();
mw.EmitCallvirt(ilgen);
this.ReturnType.EmitConvStackToParameterType(ilgen, null);
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
ilgen.Emit(OpCodes.Ret);
ilgen.MarkLabel(skip);
ilgen.Emit(OpCodes.Pop);
@ -1385,7 +1386,7 @@ namespace IKVM.Internal
{
if(instr is IKVM.Internal.MapXml.Ret)
{
this.ReturnType.EmitConvStackToParameterType(ilgen, null);
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
}
instr.Generate(context, ilgen);
}
@ -1428,7 +1429,7 @@ namespace IKVM.Internal
}
ilgen.Emit(OpCodes.Callvirt, overrideMethod);
}
this.ReturnType.EmitConvStackToParameterType(ilgen, null);
this.ReturnType.EmitConvStackTypeToSignatureType(ilgen, null);
ilgen.Emit(OpCodes.Ret);
}
ilgen.EmitLineNumberTable(mbHelper);
@ -1439,7 +1440,7 @@ namespace IKVM.Internal
{
RemapperTypeWrapper typeWrapper = (RemapperTypeWrapper)DeclaringType;
Type[] argTypes = new Type[paramTypes.Length + 1];
argTypes[0] = typeWrapper.TypeAsParameterType;
argTypes[0] = typeWrapper.TypeAsSignatureType;
this.GetParametersForDefineMethod().CopyTo(argTypes, 1);
MethodBuilder mb = typeWrapper.typeBuilder.DefineMethod("nonvirtualhelper/" + this.Name, MethodAttributes.Private | MethodAttributes.Static, this.ReturnTypeForDefineMethod, argTypes);
AttributeHelper.HideFromJava(mb);
@ -1504,13 +1505,6 @@ namespace IKVM.Internal
mw.Link();
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;
}
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;
if(f.Constant != null)
{
@ -1649,6 +1643,9 @@ namespace IKVM.Internal
// sure the inherited methods don't show up in Intellisense.
Hashtable methods = new Hashtable();
foreach(MethodInfo mi in typeBuilder.BaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static))
{
string key = MakeMethodKey(mi);
if(!methods.ContainsKey(key))
{
ParameterInfo[] paramInfo = mi.GetParameters();
Type[] paramTypes = new Type[paramInfo.Length];
@ -1670,7 +1667,8 @@ namespace IKVM.Internal
}
ilgen.Emit(OpCodes.Call, mi);
ilgen.Emit(OpCodes.Ret);
methods[mb.Name] = mb;
methods[key] = mb;
}
}
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);
if(pi.CanRead)
{
pb.SetGetMethod((MethodBuilder)methods[pi.GetGetMethod().Name]);
pb.SetGetMethod((MethodBuilder)methods[MakeMethodKey(pi.GetGetMethod())]);
}
if(pi.CanWrite)
{
pb.SetSetMethod((MethodBuilder)methods[pi.GetSetMethod().Name]);
pb.SetSetMethod((MethodBuilder)methods[MakeMethodKey(pi.GetSetMethod())]);
}
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)
{
// FXBUG .NET 1.1 doesn't allow static methods on interfaces