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

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2014-11-06 15:29:25 +0300
committerjfrijters <jfrijters>2014-11-06 15:29:25 +0300
commit7a47050861f1006cee45a1b6f3e07623247e0aa6 (patch)
treed0bcb22922edc726b1f4b1ba7acaa014f571808f
parent32448a0634a95e9380581e300be82faff56834d8 (diff)
Made sun.misc.Unsafe array access more compatible with JDK. It is now possible to get/set primitive values from arrays of a different (primitive) type
-rw-r--r--openjdk/sun/misc/Unsafe.java286
-rw-r--r--runtime/openjdk/sun.misc.cs512
2 files changed, 744 insertions, 54 deletions
diff --git a/openjdk/sun/misc/Unsafe.java b/openjdk/sun/misc/Unsafe.java
index 748e3b02..1f8ae26a 100644
--- a/openjdk/sun/misc/Unsafe.java
+++ b/openjdk/sun/misc/Unsafe.java
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2006-2012 Jeroen Frijters
+ Copyright (C) 2006-2014 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,7 @@
package sun.misc;
+import cli.System.Buffer;
import cli.System.IntPtr;
import cli.System.Runtime.InteropServices.Marshal;
import cli.System.Security.Permissions.SecurityAction;
@@ -49,7 +50,7 @@ public final class Unsafe
@sun.reflect.CallerSensitive
public static Unsafe getUnsafe()
{
- if(ikvm.internal.CallerID.getCallerID().getCallerClassLoader() != null)
+ if(!VM.isSystemDomainLoader(ikvm.internal.CallerID.getCallerID().getCallerClassLoader()))
{
throw new SecurityException("Unsafe");
}
@@ -59,7 +60,7 @@ public final class Unsafe
// this is the intrinsified version of objectFieldOffset(XXX.class.getDeclaredField("xxx"))
public long objectFieldOffset(Class c, String field)
{
- return fieldOffset(ReflectHelper.createFieldAndMakeAccessible(c, field));
+ return allocateUnsafeFieldId(ReflectHelper.createFieldAndMakeAccessible(c, field));
}
// NOTE we have a really lame (and slow) implementation!
@@ -69,12 +70,17 @@ public final class Unsafe
{
throw new IllegalArgumentException();
}
- return fieldOffset(field);
+ return allocateUnsafeFieldId(field);
}
@Deprecated
public int fieldOffset(Field original)
{
+ return allocateUnsafeFieldId(original);
+ }
+
+ static int allocateUnsafeFieldId(Field original)
+ {
Field copy = ReflectHelper.copyFieldAndMakeAccessible(original);
synchronized(fields)
{
@@ -92,6 +98,22 @@ public final class Unsafe
public int arrayIndexScale(Class c)
{
+ if (c == byte[].class || c == boolean[].class)
+ {
+ return 1;
+ }
+ if (c == char[].class || c == short[].class)
+ {
+ return 2;
+ }
+ if (c == int[].class || c == float[].class)
+ {
+ return 4;
+ }
+ if (c == long[].class || c == double[].class)
+ {
+ return 8;
+ }
// don't change this, the Unsafe intrinsics depend on this value
return 1;
}
@@ -199,17 +221,22 @@ public final class Unsafe
}
}
+ private static native short ReadInt16(Object obj, long offset);
+ private static native int ReadInt32(Object obj, long offset);
+ private static native long ReadInt64(Object obj, long offset);
+ private static native void WriteInt16(Object obj, long offset, short value);
+ private static native void WriteInt32(Object obj, long offset, int value);
+ private static native void WriteInt64(Object obj, long offset, long value);
+
public boolean compareAndSwapInt(Object obj, long offset, int expect, int update)
{
- if(obj instanceof int[])
+ if (obj instanceof cli.System.Array)
{
- int[] arr = (int[])obj;
- int index = (int)offset;
synchronized(this)
{
- if(arr[index] == expect)
+ if(ReadInt32(obj, offset) == expect)
{
- arr[index] = update;
+ WriteInt32(obj, offset, update);
return true;
}
return false;
@@ -239,11 +266,11 @@ public final class Unsafe
public void putIntVolatile(Object obj, long offset, int newValue)
{
- if(obj instanceof int[])
+ if (obj instanceof cli.System.Array)
{
synchronized(this)
{
- ((int[])obj)[(int)offset] = newValue;
+ WriteInt32(obj, offset, newValue);
}
}
else
@@ -270,11 +297,11 @@ public final class Unsafe
public int getIntVolatile(Object obj, long offset)
{
- if(obj instanceof int[])
+ if (obj instanceof cli.System.Array)
{
synchronized(this)
{
- return ((int[])obj)[(int)offset];
+ return ReadInt32(obj, offset);
}
}
else
@@ -296,15 +323,13 @@ public final class Unsafe
public boolean compareAndSwapLong(Object obj, long offset, long expect, long update)
{
- if(obj instanceof long[])
+ if (obj instanceof cli.System.Array)
{
- long[] arr = (long[])obj;
- int index = (int)offset;
synchronized(this)
{
- if(arr[index] == expect)
+ if(ReadInt64(obj, offset) == expect)
{
- arr[index] = update;
+ WriteInt64(obj, offset, update);
return true;
}
return false;
@@ -334,11 +359,11 @@ public final class Unsafe
public void putLongVolatile(Object obj, long offset, long newValue)
{
- if(obj instanceof long[])
+ if (obj instanceof cli.System.Array)
{
synchronized(this)
{
- ((long[])obj)[(int)offset] = newValue;
+ WriteInt64(obj, offset, newValue);
}
}
else
@@ -365,11 +390,11 @@ public final class Unsafe
public long getLongVolatile(Object obj, long offset)
{
- if(obj instanceof long[])
+ if (obj instanceof cli.System.Array)
{
synchronized(this)
{
- return ((long[])obj)[(int)offset];
+ return ReadInt64(obj, offset);
}
}
else
@@ -391,9 +416,9 @@ public final class Unsafe
public void putBoolean(Object obj, long offset, boolean newValue)
{
- if (obj instanceof boolean[])
+ if (obj instanceof cli.System.Array)
{
- ((boolean[])obj)[(int)offset] = newValue;
+ Buffer.SetByte((cli.System.Array)obj, (int)offset, newValue ? (byte)1 : (byte)0);
}
else
{
@@ -408,11 +433,16 @@ public final class Unsafe
}
}
+ public void putBooleanVolatile(Object obj, long offset, boolean newValue)
+ {
+ putBoolean(obj, offset, newValue);
+ }
+
public boolean getBoolean(Object obj, long offset)
{
- if (obj instanceof boolean[])
+ if (obj instanceof cli.System.Array)
{
- return ((boolean[])obj)[(int)offset];
+ return Buffer.GetByte((cli.System.Array)obj, (int)offset) != 0;
}
else
{
@@ -427,11 +457,16 @@ public final class Unsafe
}
}
+ public boolean getBooleanVolatile(Object obj, long offset)
+ {
+ return getBoolean(obj, offset);
+ }
+
public void putByte(Object obj, long offset, byte newValue)
{
- if (obj instanceof byte[])
+ if (obj instanceof cli.System.Array)
{
- ((byte[])obj)[(int)offset] = newValue;
+ Buffer.SetByte((cli.System.Array)obj, (int)offset, newValue);
}
else
{
@@ -446,11 +481,16 @@ public final class Unsafe
}
}
+ public void putByteVolatile(Object obj, long offset, byte newValue)
+ {
+ putByte(obj, offset, newValue);
+ }
+
public byte getByte(Object obj, long offset)
{
- if (obj instanceof byte[])
+ if (obj instanceof cli.System.Array)
{
- return ((byte[])obj)[(int)offset];
+ return Buffer.GetByte((cli.System.Array)obj, (int)offset);
}
else
{
@@ -465,11 +505,16 @@ public final class Unsafe
}
}
+ public byte getByteVolatile(Object obj, long offset)
+ {
+ return getByte(obj, offset);
+ }
+
public void putChar(Object obj, long offset, char newValue)
{
- if (obj instanceof char[])
+ if (obj instanceof cli.System.Array)
{
- ((char[])obj)[(int)offset] = newValue;
+ WriteInt16(obj, offset, (short)newValue);
}
else
{
@@ -484,11 +529,16 @@ public final class Unsafe
}
}
+ public void putCharVolatile(Object obj, long offset, char newValue)
+ {
+ putChar(obj, offset, newValue);
+ }
+
public char getChar(Object obj, long offset)
{
- if (obj instanceof char[])
+ if (obj instanceof cli.System.Array)
{
- return ((char[])obj)[(int)offset];
+ return (char)ReadInt16(obj, offset);
}
else
{
@@ -503,11 +553,16 @@ public final class Unsafe
}
}
+ public char getCharVolatile(Object obj, long offset)
+ {
+ return getChar(obj, offset);
+ }
+
public void putShort(Object obj, long offset, short newValue)
{
- if (obj instanceof short[])
+ if (obj instanceof cli.System.Array)
{
- ((short[])obj)[(int)offset] = newValue;
+ WriteInt16(obj, offset, newValue);
}
else
{
@@ -522,11 +577,16 @@ public final class Unsafe
}
}
+ public void putShortVolatile(Object obj, long offset, short newValue)
+ {
+ putShort(obj, offset, newValue);
+ }
+
public short getShort(Object obj, long offset)
{
- if (obj instanceof short[])
+ if (obj instanceof cli.System.Array)
{
- return ((short[])obj)[(int)offset];
+ return ReadInt16(obj, offset);
}
else
{
@@ -541,11 +601,16 @@ public final class Unsafe
}
}
+ public short getShortVolatile(Object obj, long offset)
+ {
+ return getShort(obj, offset);
+ }
+
public void putInt(Object obj, long offset, int newValue)
{
- if (obj instanceof int[])
+ if (obj instanceof cli.System.Array)
{
- ((int[])obj)[(int)offset] = newValue;
+ WriteInt32(obj, offset, newValue);
}
else
{
@@ -562,9 +627,9 @@ public final class Unsafe
public int getInt(Object obj, long offset)
{
- if (obj instanceof int[])
+ if (obj instanceof cli.System.Array)
{
- return ((int[])obj)[(int)offset];
+ return ReadInt32(obj, offset);
}
else
{
@@ -581,9 +646,9 @@ public final class Unsafe
public void putFloat(Object obj, long offset, float newValue)
{
- if (obj instanceof float[])
+ if (obj instanceof cli.System.Array)
{
- ((float[])obj)[(int)offset] = newValue;
+ WriteInt32(obj, offset, Float.floatToRawIntBits(newValue));
}
else
{
@@ -598,11 +663,16 @@ public final class Unsafe
}
}
+ public void putFloatVolatile(Object obj, long offset, float newValue)
+ {
+ putFloat(obj, offset, newValue);
+ }
+
public float getFloat(Object obj, long offset)
{
- if (obj instanceof float[])
+ if (obj instanceof cli.System.Array)
{
- return ((float[])obj)[(int)offset];
+ return Float.intBitsToFloat(ReadInt32(obj, offset));
}
else
{
@@ -617,11 +687,16 @@ public final class Unsafe
}
}
+ public float getFloatVolatile(Object obj, long offset)
+ {
+ return getFloat(obj, offset);
+ }
+
public void putLong(Object obj, long offset, long newValue)
{
- if (obj instanceof long[])
+ if (obj instanceof cli.System.Array)
{
- ((long[])obj)[(int)offset] = newValue;
+ WriteInt64(obj, offset, newValue);
}
else
{
@@ -638,9 +713,9 @@ public final class Unsafe
public long getLong(Object obj, long offset)
{
- if (obj instanceof long[])
+ if (obj instanceof cli.System.Array)
{
- return ((long[])obj)[(int)offset];
+ return ReadInt64(obj, offset);
}
else
{
@@ -657,9 +732,9 @@ public final class Unsafe
public void putDouble(Object obj, long offset, double newValue)
{
- if (obj instanceof double[])
+ if (obj instanceof cli.System.Array)
{
- ((double[])obj)[(int)offset] = newValue;
+ WriteInt64(obj, offset, Double.doubleToRawLongBits(newValue));
}
else
{
@@ -674,11 +749,19 @@ public final class Unsafe
}
}
+ public void putDoubleVolatile(Object obj, long offset, double newValue)
+ {
+ synchronized (this)
+ {
+ putDouble(obj, offset, newValue);
+ }
+ }
+
public double getDouble(Object obj, long offset)
{
- if (obj instanceof double[])
+ if (obj instanceof cli.System.Array)
{
- return ((double[])obj)[(int)offset];
+ return Double.longBitsToDouble(ReadInt64(obj, offset));
}
else
{
@@ -693,6 +776,14 @@ public final class Unsafe
}
}
+ public double getDoubleVolatile(Object obj, long offset)
+ {
+ synchronized (this)
+ {
+ return getDouble(obj, offset);
+ }
+ }
+
public void putObject(Object obj, long offset, Object newValue)
{
if (obj instanceof Object[])
@@ -1122,6 +1213,10 @@ public final class Unsafe
}
else
{
+ if (time == 0)
+ {
+ time = Long.MAX_VALUE;
+ }
java.util.concurrent.locks.LockSupport.parkNanos(time);
}
}
@@ -1136,8 +1231,16 @@ public final class Unsafe
return null;
}
+ public native boolean shouldBeInitialized(Class<?> c);
+
public native Class defineClass(String name, byte[] buf, int offset, int length, ClassLoader cl, ProtectionDomain pd);
+ @Deprecated
+ @sun.reflect.CallerSensitive
+ public native Class defineClass(String name, byte[] b, int off, int len);
+
+ public native Class defineAnonymousClass(Class hostClass, byte[] data, Object[] cpPatches);
+
public void monitorEnter(Object o)
{
cli.System.Threading.Monitor.Enter(o);
@@ -1152,4 +1255,79 @@ public final class Unsafe
{
return cli.System.Threading.Monitor.TryEnter(o);
}
+
+ public final int getAndAddInt(Object o, long offset, int delta)
+ {
+ for (;;)
+ {
+ int value = getIntVolatile(o, offset);
+ if (compareAndSwapInt(o, offset, value, value + delta))
+ {
+ return value;
+ }
+ }
+ }
+
+ public final long getAndAddLong(Object o, long offset, long delta)
+ {
+ for (;;)
+ {
+ long value = getLongVolatile(o, offset);
+ if (compareAndSwapLong(o, offset, value, value + delta))
+ {
+ return value;
+ }
+ }
+ }
+
+ public final int getAndSetInt(Object o, long offset, int newValue)
+ {
+ for (;;)
+ {
+ int value = getIntVolatile(o, offset);
+ if (compareAndSwapInt(o, offset, value, newValue))
+ {
+ return value;
+ }
+ }
+ }
+
+ public final long getAndSetLong(Object o, long offset, long newValue)
+ {
+ for (;;)
+ {
+ long value = getLongVolatile(o, offset);
+ if (compareAndSwapLong(o, offset, value, newValue))
+ {
+ return value;
+ }
+ }
+ }
+
+ public final Object getAndSetObject(Object o, long offset, Object newValue)
+ {
+ for (;;)
+ {
+ Object value = getObjectVolatile(o, offset);
+ if (compareAndSwapObject(o, offset, value, newValue))
+ {
+ return value;
+ }
+ }
+ }
+
+ public void loadFence()
+ {
+ cli.System.Threading.Thread.MemoryBarrier();
+ }
+
+ public void storeFence()
+ {
+ cli.System.Threading.Thread.MemoryBarrier();
+ }
+
+ public void fullFence()
+ {
+ cli.System.Threading.Thread.MemoryBarrier();
+ }
}
diff --git a/runtime/openjdk/sun.misc.cs b/runtime/openjdk/sun.misc.cs
new file mode 100644
index 00000000..90399a86
--- /dev/null
+++ b/runtime/openjdk/sun.misc.cs
@@ -0,0 +1,512 @@
+/*
+ Copyright (C) 2007-2014 Jeroen Frijters
+ Copyright (C) 2009 Volker Berlin (i-net software)
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security;
+using IKVM.Internal;
+
+static class Java_sun_misc_GC
+{
+ public static long maxObjectInspectionAge()
+ {
+ return 0;
+ }
+}
+
+static class Java_sun_misc_MessageUtils
+{
+ public static void toStderr(string msg)
+ {
+ Console.Error.Write(msg);
+ }
+
+ public static void toStdout(string msg)
+ {
+ Console.Out.Write(msg);
+ }
+}
+
+static class Java_sun_misc_MiscHelper
+{
+ public static object getAssemblyClassLoader(Assembly asm, object extcl)
+ {
+ if (extcl == null || asm.IsDefined(typeof(IKVM.Attributes.CustomAssemblyClassLoaderAttribute), false))
+ {
+ return AssemblyClassLoader.FromAssembly(asm).GetJavaClassLoader();
+ }
+ return null;
+ }
+}
+
+static class Java_sun_misc_Signal
+{
+ /* derived from version 6.0 VC98/include/signal.h */
+ private const int SIGINT = 2; /* interrupt */
+ private const int SIGILL = 4; /* illegal instruction - invalid function image */
+ private const int SIGFPE = 8; /* floating point exception */
+ private const int SIGSEGV = 11; /* segment violation */
+ private const int SIGTERM = 15; /* Software termination signal from kill */
+ private const int SIGBREAK = 21; /* Ctrl-Break sequence */
+ private const int SIGABRT = 22; /* abnormal termination triggered by abort call */
+
+ private static Dictionary<int, long> handler = new Dictionary<int, long>();
+
+ // Delegate type to be used as the Handler Routine for SetConsoleCtrlHandler
+ private delegate Boolean ConsoleCtrlDelegate(CtrlTypes CtrlType);
+
+ // Enumerated type for the control messages sent to the handler routine
+ private enum CtrlTypes : uint
+ {
+ CTRL_C_EVENT = 0,
+ CTRL_BREAK_EVENT,
+ CTRL_CLOSE_EVENT,
+ CTRL_LOGOFF_EVENT = 5,
+ CTRL_SHUTDOWN_EVENT
+ }
+
+ [SecurityCritical]
+ private sealed class CriticalCtrlHandler : CriticalFinalizerObject
+ {
+ private ConsoleCtrlDelegate consoleCtrlDelegate;
+ private bool ok;
+
+ [DllImport("kernel32.dll")]
+ private static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate e, bool add);
+
+ internal CriticalCtrlHandler()
+ {
+ consoleCtrlDelegate = new ConsoleCtrlDelegate(ConsoleCtrlCheck);
+ ok = SetConsoleCtrlHandler(consoleCtrlDelegate, true);
+ }
+
+ [SecuritySafeCritical]
+ ~CriticalCtrlHandler()
+ {
+ if (ok)
+ {
+ SetConsoleCtrlHandler(consoleCtrlDelegate, false);
+ }
+ }
+ }
+
+ private static object defaultConsoleCtrlDelegate;
+
+ private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
+ {
+#if !FIRST_PASS
+ switch (ctrlType)
+ {
+ case CtrlTypes.CTRL_BREAK_EVENT:
+ DumpAllJavaThreads();
+ return true;
+
+ }
+#endif
+ return false;
+ }
+
+#if !FIRST_PASS
+ private static void DumpAllJavaThreads()
+ {
+ Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
+ java.util.Map traces = java.lang.Thread.getAllStackTraces();
+ Console.WriteLine("Full thread dump IKVM.NET {0} ({1} bit):", JVM.SafeGetAssemblyVersion(Assembly.GetExecutingAssembly()), IntPtr.Size * 8);
+ java.util.Iterator entries = traces.entrySet().iterator();
+ while (entries.hasNext())
+ {
+ java.util.Map.Entry entry = (java.util.Map.Entry)entries.next();
+ java.lang.Thread thread = (java.lang.Thread)entry.getKey();
+ Console.WriteLine("\n\"{0}\"{1} prio={2} tid=0x{3:X8}", thread.getName(), thread.isDaemon() ? " daemon" : "", thread.getPriority(), thread.getId());
+ Console.WriteLine(" java.lang.Thread.State: " + thread.getState());
+ java.lang.StackTraceElement[] trace = (java.lang.StackTraceElement[])entry.getValue();
+ for (int i = 0; i < trace.Length; i++)
+ {
+ Console.WriteLine("\tat {0}", trace[i]);
+ }
+ }
+ Console.WriteLine();
+ }
+#endif
+
+ public static int findSignal(string sigName)
+ {
+ if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+ {
+ switch (sigName)
+ {
+ case "ABRT": /* abnormal termination triggered by abort cl */
+ return SIGABRT;
+ case "FPE": /* floating point exception */
+ return SIGFPE;
+ case "SEGV": /* segment violation */
+ return SIGSEGV;
+ case "INT": /* interrupt */
+ return SIGINT;
+ case "TERM": /* software term signal from kill */
+ return SIGTERM;
+ case "BREAK": /* Ctrl-Break sequence */
+ return SIGBREAK;
+ case "ILL": /* illegal instruction */
+ return SIGILL;
+ }
+ }
+ return -1;
+ }
+
+ // this is a separate method to be able to catch the SecurityException (for the LinkDemand)
+ [SecuritySafeCritical]
+ private static void RegisterCriticalCtrlHandler()
+ {
+ defaultConsoleCtrlDelegate = new CriticalCtrlHandler();
+ }
+
+ // Register a signal handler
+ public static long handle0(int sig, long nativeH)
+ {
+ long oldHandler;
+ handler.TryGetValue(sig, out oldHandler);
+ switch (nativeH)
+ {
+ case 0: // Default Signal Handler
+ if (defaultConsoleCtrlDelegate == null && Environment.OSVersion.Platform == PlatformID.Win32NT)
+ {
+ try
+ {
+ RegisterCriticalCtrlHandler();
+ }
+ catch (SecurityException)
+ {
+ }
+ }
+ break;
+ case 1: // Ignore Signal
+ break;
+ case 2: // Custom Signal Handler
+ switch (sig)
+ {
+ case SIGBREAK:
+ case SIGFPE:
+ return -1;
+ }
+ break;
+ }
+ handler[sig] = nativeH;
+ return oldHandler;
+ }
+
+ public static void raise0(int sig)
+ {
+#if !FIRST_PASS
+ java.security.AccessController.doPrivileged(ikvm.runtime.Delegates.toPrivilegedAction(delegate
+ {
+ java.lang.Class clazz = typeof(sun.misc.Signal);
+ java.lang.reflect.Method dispatch = clazz.getDeclaredMethod("dispatch", java.lang.Integer.TYPE);
+ dispatch.setAccessible(true);
+ dispatch.invoke(null, java.lang.Integer.valueOf(sig));
+ return null;
+ }));
+#endif
+ }
+}
+
+static class Java_sun_misc_NativeSignalHandler
+{
+ public static void handle0(int number, long handler)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+static class Java_sun_misc_Perf
+{
+ public static object attach(object thisPerf, string user, int lvmid, int mode)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void detach(object thisPerf, object bb)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static object createLong(object thisPerf, string name, int variability, int units, long value)
+ {
+#if FIRST_PASS
+ return null;
+#else
+ return java.nio.ByteBuffer.allocate(8);
+#endif
+ }
+
+ public static object createByteArray(object thisPerf, string name, int variability, int units, byte[] value, int maxLength)
+ {
+#if FIRST_PASS
+ return null;
+#else
+ return java.nio.ByteBuffer.allocate(maxLength).put(value);
+#endif
+ }
+
+ public static long highResCounter(object thisPerf)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static long highResFrequency(object thisPerf)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void registerNatives()
+ {
+ }
+}
+
+static class Java_sun_misc_Unsafe
+{
+ private static void CheckArrayBounds(object obj, long offset, int accessLength)
+ {
+ // NOTE we rely on the fact that Buffer.ByteLength() requires a primitive array
+ int arrayLength = Buffer.ByteLength((Array)obj);
+ if (offset < 0 || offset > arrayLength - accessLength || accessLength > arrayLength)
+ {
+ throw new IndexOutOfRangeException();
+ }
+ }
+
+ [SecuritySafeCritical]
+ public static short ReadInt16(object obj, long offset)
+ {
+ CheckArrayBounds(obj, offset, 2);
+ GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+ short value = Marshal.ReadInt16((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset));
+ handle.Free();
+ return value;
+ }
+
+ [SecuritySafeCritical]
+ public static int ReadInt32(object obj, long offset)
+ {
+ CheckArrayBounds(obj, offset, 4);
+ GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+ int value = Marshal.ReadInt32((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset));
+ handle.Free();
+ return value;
+ }
+
+ [SecuritySafeCritical]
+ public static long ReadInt64(object obj, long offset)
+ {
+ CheckArrayBounds(obj, offset, 8);
+ GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+ long value = Marshal.ReadInt64((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset));
+ handle.Free();
+ return value;
+ }
+
+ [SecuritySafeCritical]
+ public static void WriteInt16(object obj, long offset, short value)
+ {
+ CheckArrayBounds(obj, offset, 2);
+ GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+ Marshal.WriteInt16((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value);
+ handle.Free();
+ }
+
+ [SecuritySafeCritical]
+ public static void WriteInt32(object obj, long offset, int value)
+ {
+ CheckArrayBounds(obj, offset, 4);
+ GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+ Marshal.WriteInt32((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value);
+ handle.Free();
+ }
+
+ [SecuritySafeCritical]
+ public static void WriteInt64(object obj, long offset, long value)
+ {
+ CheckArrayBounds(obj, offset, 8);
+ GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
+ Marshal.WriteInt64((IntPtr)(handle.AddrOfPinnedObject().ToInt64() + offset), value);
+ handle.Free();
+ }
+
+ public static void throwException(object thisUnsafe, Exception x)
+ {
+ throw x;
+ }
+
+ public static bool shouldBeInitialized(object thisUnsafe, java.lang.Class clazz)
+ {
+ return TypeWrapper.FromClass(clazz).HasStaticInitializer;
+ }
+
+ public static void ensureClassInitialized(object thisUnsafe, java.lang.Class clazz)
+ {
+ TypeWrapper tw = TypeWrapper.FromClass(clazz);
+ if (!tw.IsArray)
+ {
+ try
+ {
+ tw.Finish();
+ }
+ catch (RetargetableJavaException x)
+ {
+ throw x.ToJava();
+ }
+ tw.RunClassInit();
+ }
+ }
+
+ [SecurityCritical]
+ public static object allocateInstance(object thisUnsafe, java.lang.Class clazz)
+ {
+ TypeWrapper wrapper = TypeWrapper.FromClass(clazz);
+ try
+ {
+ wrapper.Finish();
+ }
+ catch (RetargetableJavaException x)
+ {
+ throw x.ToJava();
+ }
+ return FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType);
+ }
+
+ public static java.lang.Class defineClass(object thisUnsafe, string name, byte[] buf, int offset, int length, java.lang.ClassLoader cl, java.security.ProtectionDomain pd)
+ {
+ return Java_java_lang_ClassLoader.defineClass1(cl, name.Replace('/', '.'), buf, offset, length, pd, null);
+ }
+
+ public static java.lang.Class defineClass(object thisUnsafe, string name, byte[] buf, int offset, int length, ikvm.@internal.CallerID callerID)
+ {
+#if FIRST_PASS
+ return null;
+#else
+ return defineClass(thisUnsafe, name, buf, offset, length, callerID.getCallerClassLoader(), callerID.getCallerClass().pd);
+#endif
+ }
+
+ public static java.lang.Class defineAnonymousClass(object thisUnsafe, java.lang.Class host, byte[] data, object[] cpPatches)
+ {
+#if FIRST_PASS
+ return null;
+#else
+ try
+ {
+ ClassLoaderWrapper loader = TypeWrapper.FromClass(host).GetClassLoader();
+ ClassFile classFile = new ClassFile(data, 0, data.Length, "<Unknown>", loader.ClassFileParseOptions, cpPatches);
+ if (classFile.IKVMAssemblyAttribute != null)
+ {
+ // if this happens, the OpenJDK is probably trying to load an OpenJDK class file as a resource,
+ // make sure the build process includes the original class file as a resource in that case
+ throw new java.lang.ClassFormatError("Trying to define anonymous class based on stub class: " + classFile.Name);
+ }
+ return loader.GetTypeWrapperFactory().DefineClassImpl(null, TypeWrapper.FromClass(host), classFile, loader, host.pd).ClassObject;
+ }
+ catch (RetargetableJavaException x)
+ {
+ throw x.ToJava();
+ }
+#endif
+ }
+}
+
+static class Java_sun_misc_Version
+{
+ public static string getJvmSpecialVersion()
+ {
+ throw new NotImplementedException();
+ }
+
+ public static string getJdkSpecialVersion()
+ {
+ throw new NotImplementedException();
+ }
+
+ public static bool getJvmVersionInfo()
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void getJdkVersionInfo()
+ {
+ throw new NotImplementedException();
+ }
+}
+
+static class Java_sun_misc_VM
+{
+ public static void initialize()
+ {
+ }
+
+ public static java.lang.ClassLoader latestUserDefinedLoader()
+ {
+ // testing shows that it is cheaper the get the full stack trace and then look at a few frames than getting the frames individually
+ StackTrace trace = new StackTrace(2, false);
+ for (int i = 0; i < trace.FrameCount; i++)
+ {
+ StackFrame frame = trace.GetFrame(i);
+ MethodBase method = frame.GetMethod();
+ if (method == null)
+ {
+ continue;
+ }
+ Type type = method.DeclaringType;
+ if (type != null)
+ {
+ TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type);
+ if (tw != null)
+ {
+ ClassLoaderWrapper classLoader = tw.GetClassLoader();
+ AssemblyClassLoader acl = classLoader as AssemblyClassLoader;
+ if (acl == null || acl.GetAssembly(tw) != typeof(object).Assembly)
+ {
+ java.lang.ClassLoader javaClassLoader = classLoader.GetJavaClassLoader();
+ if (javaClassLoader != null)
+ {
+ return javaClassLoader;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+}
+
+static class Java_sun_misc_VMSupport
+{
+ public static object initAgentProperties(object props)
+ {
+ return props;
+ }
+}