ikvm-fork/runtime/ByteCodeHelper.cs

793 строки
21 KiB
C#
Исходник Обычный вид История

2002-12-18 19:00:25 +03:00
/*
Copyright (C) 2002-2008 Jeroen Frijters
2002-12-18 19:00:25 +03:00
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;
2003-01-06 19:30:09 +03:00
using System.Reflection;
2004-03-20 16:25:08 +03:00
using System.Diagnostics;
2006-06-08 13:26:33 +04:00
using System.Threading;
2005-05-26 10:53:50 +04:00
using IKVM.Attributes;
2005-06-01 13:49:30 +04:00
using IKVM.Internal;
using System.Runtime.InteropServices;
2002-12-18 19:00:25 +03:00
2004-09-09 15:17:55 +04:00
namespace IKVM.Runtime
2002-12-18 19:00:25 +03:00
{
static class GhostTag
{
private static volatile PassiveWeakDictionary<object, TypeWrapper> dict;
internal static void SetTag(object obj, RuntimeTypeHandle typeHandle)
{
SetTag(obj, ClassLoaderWrapper.GetWrapperFromType(Type.GetTypeFromHandle(typeHandle)));
}
internal static void SetTag(object obj, TypeWrapper wrapper)
{
if(dict == null)
{
PassiveWeakDictionary<object, TypeWrapper> newDict = new PassiveWeakDictionary<object, TypeWrapper>();
#pragma warning disable 0420 // don't whine about CompareExchange not respecting 'volatile'
if(Interlocked.CompareExchange(ref dict, newDict, null) != null)
#pragma warning restore
{
newDict.Dispose();
}
}
dict.Add(obj, wrapper);
}
internal static TypeWrapper GetTag(object obj)
{
if(dict != null)
{
TypeWrapper tw;
dict.TryGetValue(obj, out tw);
return tw;
}
return null;
}
// this method is called from <GhostType>.IsInstanceArray()
internal static bool IsGhostArrayInstance(object obj, RuntimeTypeHandle typeHandle, int rank)
{
TypeWrapper tw1 = GhostTag.GetTag(obj);
if(tw1 != null)
{
TypeWrapper tw2 = ClassLoaderWrapper.GetWrapperFromType(Type.GetTypeFromHandle(typeHandle)).MakeArrayType(rank);
return tw1.IsAssignableTo(tw2);
}
return false;
}
}
2007-12-18 14:04:53 +03:00
public static class ByteCodeHelper
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object multianewarray(RuntimeTypeHandle typeHandle, int[] lengths)
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
for(int i = 0; i < lengths.Length; i++)
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
if(lengths[i] < 0)
{
#if !FIRST_PASS
throw new java.lang.NegativeArraySizeException();
#endif
2004-09-09 15:17:55 +04:00
}
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
return MultianewarrayHelper(Type.GetTypeFromHandle(typeHandle).GetElementType(), lengths, 0);
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
private static object MultianewarrayHelper(Type elemType, int[] lengths, int index)
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
object o = Array.CreateInstance(elemType, lengths[index++]);
if(index < lengths.Length)
2002-12-18 19:00:25 +03:00
{
2004-09-09 15:17:55 +04:00
elemType = elemType.GetElementType();
object[] a = (object[])o;
for(int i = 0; i < a.Length; i++)
{
a[i] = MultianewarrayHelper(elemType, lengths, index);
}
2002-12-18 19:00:25 +03:00
}
2004-09-09 15:17:55 +04:00
return o;
2002-12-18 19:00:25 +03:00
}
[DebuggerStepThroughAttribute]
public static object multianewarray_ghost(RuntimeTypeHandle typeHandle, int[] lengths)
{
Type type = Type.GetTypeFromHandle(typeHandle);
int rank = 0;
while(type.IsArray)
{
rank++;
type = type.GetElementType();
}
object obj = multianewarray(ArrayTypeWrapper.MakeArrayType(typeof(object), rank).TypeHandle, lengths);
GhostTag.SetTag(obj, typeHandle);
return obj;
}
[DebuggerStepThroughAttribute]
public static T[] anewarray_ghost<T>(int length, RuntimeTypeHandle typeHandle)
{
T[] obj = new T[length];
GhostTag.SetTag(obj, typeHandle);
return obj;
}
#if !COMPACT_FRAMEWORK && !FIRST_PASS
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicMultianewarray(RuntimeTypeHandle type, string clazz, int[] lengths)
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicMultianewarray");
TypeWrapper wrapper = LoadTypeWrapper(type, clazz);
return multianewarray(wrapper.TypeAsArrayType.TypeHandle, lengths);
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicNewarray(int length, RuntimeTypeHandle type, string clazz)
{
Profiler.Count("DynamicNewarray");
if(length < 0)
{
throw new java.lang.NegativeArraySizeException();
2004-09-09 15:17:55 +04:00
}
TypeWrapper wrapper = LoadTypeWrapper(type, clazz);
return Array.CreateInstance(wrapper.TypeAsArrayType, length);
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static void DynamicAastore(object arrayref, int index, object val, RuntimeTypeHandle type, string clazz)
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicAastore");
// TODO do we need to load the type here?
((Array)arrayref).SetValue(val, index);
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicAaload(object arrayref, int index, RuntimeTypeHandle type, string clazz)
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicAaload");
// TODO do we need to load the type here?
return ((Array)arrayref).GetValue(index);
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
private static FieldWrapper GetFieldWrapper(TypeWrapper thisType, RuntimeTypeHandle type, string clazz, string name, string sig, bool isStatic)
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
TypeWrapper caller = ClassLoaderWrapper.GetWrapperFromType(Type.GetTypeFromHandle(type));
TypeWrapper wrapper = LoadTypeWrapper(type, clazz);
2004-10-04 23:30:53 +04:00
FieldWrapper field = wrapper.GetFieldWrapper(name, sig);
2004-09-09 15:17:55 +04:00
if(field == null)
{
throw new java.lang.NoSuchFieldError(clazz + "." + name);
2004-09-09 15:17:55 +04:00
}
// TODO check loader constraints
if(field.IsStatic != isStatic)
{
throw new java.lang.IncompatibleClassChangeError(clazz + "." + name);
2004-09-09 15:17:55 +04:00
}
2005-05-31 09:44:29 +04:00
if(field.IsAccessibleFrom(wrapper, caller, thisType))
2004-09-09 15:17:55 +04:00
{
return field;
}
throw new java.lang.IllegalAccessError(field.DeclaringType.Name + "." + name);
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicGetfield(object obj, string name, string sig, RuntimeTypeHandle type, string clazz)
{
Profiler.Count("DynamicGetfield");
return GetFieldWrapper(ClassLoaderWrapper.GetWrapperFromType(obj.GetType()), type, clazz, name, sig, false).GetValue(obj);
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicGetstatic(string name, string sig, RuntimeTypeHandle type, string clazz)
{
Profiler.Count("DynamicGetstatic");
return GetFieldWrapper(null, type, clazz, name, sig, true).GetValue(null);
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static void DynamicPutfield(object obj, object val, string name, string sig, RuntimeTypeHandle type, string clazz)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicPutfield");
FieldWrapper fw = GetFieldWrapper(ClassLoaderWrapper.GetWrapperFromType(obj.GetType()), type, clazz, name, sig, false);
if(fw.IsFinal)
{
throw new java.lang.IllegalAccessError("Field " + fw.DeclaringType.Name + "." + fw.Name + " is final");
2004-09-09 15:17:55 +04:00
}
fw.SetValue(obj, val);
2004-08-17 13:05:21 +04:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static void DynamicPutstatic(object val, string name, string sig, RuntimeTypeHandle type, string clazz)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicPutstatic");
FieldWrapper fw = GetFieldWrapper(null, type, clazz, name, sig, true);
if(fw.IsFinal)
{
throw new java.lang.IllegalAccessError("Field " + fw.DeclaringType.Name + "." + fw.Name + " is final");
2004-09-09 15:17:55 +04:00
}
fw.SetValue(null, val);
2004-08-17 13:05:21 +04:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
// the sole purpose of this method is to check whether the clazz can be instantiated (but not to actually do it)
[DebuggerStepThroughAttribute]
public static void DynamicNewCheckOnly(RuntimeTypeHandle type, string clazz)
2004-01-11 16:14:42 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicNewCheckOnly");
TypeWrapper wrapper = LoadTypeWrapper(type, clazz);
2004-10-19 17:43:55 +04:00
if(wrapper.IsAbstract)
2004-09-09 15:17:55 +04:00
{
throw new java.lang.InstantiationError(clazz);
2004-09-09 15:17:55 +04:00
}
2005-08-24 12:14:23 +04:00
wrapper.RunClassInit();
2004-01-11 16:14:42 +03:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
private static TypeWrapper LoadTypeWrapper(RuntimeTypeHandle type, string clazz)
2003-05-30 16:08:59 +04:00
{
2004-09-09 15:17:55 +04:00
try
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
TypeWrapper context = ClassLoaderWrapper.GetWrapperFromType(Type.GetTypeFromHandle(type));
TypeWrapper wrapper = context.GetClassLoader().LoadClassByDottedNameFast(clazz);
if(wrapper == null)
{
throw new java.lang.NoClassDefFoundError(clazz);
2004-09-09 15:17:55 +04:00
}
if(!wrapper.IsAccessibleFrom(context))
{
throw new java.lang.IllegalAccessError("Try to access class " + wrapper.Name + " from class " + context.Name);
2004-09-09 15:17:55 +04:00
}
wrapper.Finish();
return wrapper;
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
catch(RetargetableJavaException x)
2004-08-17 13:05:21 +04:00
{
2005-08-25 11:46:57 +04:00
throw x.ToJava();
2004-12-21 13:26:51 +03:00
}
2003-05-30 16:08:59 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicClassLiteral(RuntimeTypeHandle type, string clazz)
2004-01-11 16:14:42 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicClassLiteral");
2004-12-21 17:59:29 +03:00
return LoadTypeWrapper(type, clazz).ClassObject;
2004-01-11 16:14:42 +03:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static object DynamicCast(object obj, RuntimeTypeHandle type, string clazz)
2003-08-12 17:09:31 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicCast");
2005-03-11 16:56:44 +03:00
// NOTE it's important that we don't try to load the class if obj == null
// (to be compatible with Sun)
if(obj != null && !DynamicInstanceOf(obj, type, clazz))
2004-09-09 15:17:55 +04:00
{
throw new java.lang.ClassCastException(NativeCode.ikvm.runtime.Util.GetTypeWrapperFromObject(obj).Name);
2004-09-09 15:17:55 +04:00
}
return obj;
2003-08-12 17:09:31 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static bool DynamicInstanceOf(object obj, RuntimeTypeHandle type, string clazz)
2003-01-06 19:30:09 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicInstanceOf");
2005-03-14 17:29:47 +03:00
// NOTE it's important that we don't try to load the class if obj == null
// (to be compatible with Sun)
if(obj == null)
{
return false;
}
2004-09-09 15:17:55 +04:00
TypeWrapper wrapper = LoadTypeWrapper(type, clazz);
return wrapper.IsInstance(obj);
2003-01-06 19:30:09 +03:00
}
2004-09-09 15:17:55 +04:00
private static MethodWrapper GetMethodWrapper(TypeWrapper thisType, RuntimeTypeHandle type, string clazz, string name, string sig, bool isStatic)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
TypeWrapper caller = ClassLoaderWrapper.GetWrapperFromType(Type.GetTypeFromHandle(type));
TypeWrapper wrapper = LoadTypeWrapper(type, clazz);
2005-01-03 11:26:21 +03:00
MethodWrapper mw = wrapper.GetMethodWrapper(name, sig, false);
2004-09-09 15:17:55 +04:00
if(mw == null)
{
throw new java.lang.NoSuchMethodError(clazz + "." + name + sig);
2004-09-09 15:17:55 +04:00
}
// TODO check loader constraints
if(mw.IsStatic != isStatic)
{
throw new java.lang.IncompatibleClassChangeError(clazz + "." + name);
2004-09-09 15:17:55 +04:00
}
2005-05-31 09:44:29 +04:00
if(mw.IsAccessibleFrom(wrapper, caller, thisType))
2004-09-09 15:17:55 +04:00
{
return mw;
}
throw new java.lang.IllegalAccessError(clazz + "." + name + sig);
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
2004-09-09 15:17:55 +04:00
public static object DynamicInvokeSpecialNew(RuntimeTypeHandle type, string clazz, string name, string sig, object[] args)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicInvokeSpecialNew");
return GetMethodWrapper(null, type, clazz, name, sig, false).Invoke(null, args, false, ikvm.@internal.CallerID.create(new StackFrame(1, false)));
2004-08-17 13:05:21 +04:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
2004-09-09 15:17:55 +04:00
public static object DynamicInvokestatic(RuntimeTypeHandle type, string clazz, string name, string sig, object[] args)
{
Profiler.Count("DynamicInvokestatic");
return GetMethodWrapper(null, type, clazz, name, sig, true).Invoke(null, args, false, ikvm.@internal.CallerID.create(new StackFrame(1, false)));
2004-09-09 15:17:55 +04:00
}
2003-08-12 17:09:31 +04:00
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
2004-09-09 15:17:55 +04:00
public static object DynamicInvokevirtual(object obj, RuntimeTypeHandle type, string clazz, string name, string sig, object[] args)
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicInvokevirtual");
return GetMethodWrapper(ClassLoaderWrapper.GetWrapperFromType(obj.GetType()), type, clazz, name, sig, false).Invoke(obj, args, false, ikvm.@internal.CallerID.create(new StackFrame(1, false)));
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static Type DynamicGetTypeAsExceptionType(RuntimeTypeHandle type, string clazz)
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler.Count("DynamicGetTypeAsExceptionType");
return LoadTypeWrapper(type, clazz).TypeAsExceptionType;
2003-02-27 19:41:47 +03:00
}
2005-12-19 18:12:49 +03:00
#else
[DebuggerStepThroughAttribute]
public static object DynamicCast(object obj, RuntimeTypeHandle type, string clazz)
{
if(obj != null)
{
#if !FIRST_PASS
throw new java.lang.ClassCastException();
#endif
2005-12-19 18:12:49 +03:00
}
return obj;
}
[DebuggerStepThroughAttribute]
public static bool DynamicInstanceOf(object obj, RuntimeTypeHandle type, string clazz)
{
return false;
}
#endif //!COMPACT_FRAMEWORK
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static int f2i(float f)
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if(f <= int.MinValue)
{
return int.MinValue;
}
if(f >= int.MaxValue)
{
return int.MaxValue;
}
2005-12-07 12:06:32 +03:00
if(float.IsNaN(f))
2004-09-09 15:17:55 +04:00
{
return 0;
}
return (int)f;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static long f2l(float f)
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if(f <= long.MinValue)
{
return long.MinValue;
}
if(f >= long.MaxValue)
{
return long.MaxValue;
}
2005-12-07 12:06:32 +03:00
if(float.IsNaN(f))
2004-09-09 15:17:55 +04:00
{
return 0;
}
return (long)f;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static int d2i(double d)
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if(d <= int.MinValue)
{
return int.MinValue;
}
if(d >= int.MaxValue)
{
return int.MaxValue;
}
2005-12-07 12:06:32 +03:00
if(double.IsNaN(d))
2004-09-09 15:17:55 +04:00
{
return 0;
}
return (int)d;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
[DebuggerStepThroughAttribute]
public static long d2l(double d)
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
if(d <= long.MinValue)
{
return long.MinValue;
}
if(d >= long.MaxValue)
{
return long.MaxValue;
}
2005-12-07 12:06:32 +03:00
if(double.IsNaN(d))
2004-09-09 15:17:55 +04:00
{
return 0;
}
return (long)d;
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
// This is used by static JNI and synchronized methods that need a class object
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static object GetClassFromTypeHandle(RuntimeTypeHandle typeHandle)
2003-02-27 19:41:47 +03:00
{
2006-08-17 11:33:38 +04:00
return NativeCode.ikvm.runtime.Util.getClassFromTypeHandle(typeHandle);
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy(object src, int srcStart, object dest, int destStart, int len)
2003-02-27 19:41:47 +03:00
{
#if !FIRST_PASS
2005-03-03 11:20:13 +03:00
// If the two arrays are the same, we can use the fast path, but we're also required to do so,
// to get the required memmove semantics.
if(src == dest)
2004-09-09 15:17:55 +04:00
{
try
{
2005-03-03 11:20:13 +03:00
arraycopy_fast((Array)src, srcStart, (Array)dest, destStart, len);
return;
}
catch(InvalidCastException)
{
throw new java.lang.ArrayStoreException();
2005-03-03 11:20:13 +03:00
}
}
else if(src == null || dest == null)
{
throw new java.lang.NullPointerException();
2005-03-03 11:20:13 +03:00
}
else if(len < 0)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2005-03-03 11:20:13 +03:00
}
else
{
object[] src1 = src as object[];
object[] dst1 = dest as object[];
if(src1 != null && dst1 != null)
{
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-03-03 11:20:13 +03:00
// for small copies, don't bother comparing the types as this is relatively expensive
if(len > 50 && Type.GetTypeHandle(src).Value == Type.GetTypeHandle(dest).Value)
{
arraycopy_fast(src1, srcStart, dst1, destStart, len);
return;
}
else
2005-12-07 12:06:32 +03:00
#endif
2004-09-09 15:17:55 +04:00
{
2005-03-03 11:20:13 +03:00
for(; len > 0; len--)
2004-09-09 15:17:55 +04:00
{
2005-03-03 11:20:13 +03:00
// NOTE we don't need to catch ArrayTypeMismatchException & IndexOutOfRangeException, because
// they automatically get converted to the Java equivalents anyway.
dst1[destStart++] = src1[srcStart++];
2004-09-09 15:17:55 +04:00
}
2005-03-03 11:20:13 +03:00
return;
2004-09-09 15:17:55 +04:00
}
}
2005-12-07 12:06:32 +03:00
#if COMPACT_FRAMEWORK
else if(src.GetType() != dest.GetType() &&
(IsPrimitiveArrayType(src.GetType()) || IsPrimitiveArrayType(dest.GetType())))
#else
2005-03-03 11:20:13 +03:00
else if(Type.GetTypeHandle(src).Value != Type.GetTypeHandle(dest).Value &&
(IsPrimitiveArrayType(src.GetType()) || IsPrimitiveArrayType(dest.GetType())))
2005-12-07 12:06:32 +03:00
#endif
2005-03-03 11:20:13 +03:00
{
// we don't want to allow copying a primitive into an object array!
throw new java.lang.ArrayStoreException();
2005-03-03 11:20:13 +03:00
}
else
2004-09-09 15:17:55 +04:00
{
2005-03-03 11:20:13 +03:00
try
{
arraycopy_fast((Array)src, srcStart, (Array)dest, destStart, len);
return;
}
catch(InvalidCastException)
{
throw new java.lang.ArrayStoreException();
2005-03-03 11:20:13 +03:00
}
2004-09-09 15:17:55 +04:00
}
}
#endif // !FIRST_PASS
2005-03-03 11:20:13 +03:00
}
private static bool IsPrimitiveArrayType(Type type)
{
return type.IsArray && ClassLoaderWrapper.GetWrapperFromType(type.GetElementType()).IsPrimitive;
}
[DebuggerStepThroughAttribute]
public static void arraycopy_fast(Array src, int srcStart, Array dest, int destStart, int len)
{
#if !FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
2005-03-03 11:20:13 +03:00
Array.Copy(src, srcStart, dest, destStart, len);
2004-09-09 15:17:55 +04:00
}
catch(ArgumentNullException)
{
throw new java.lang.NullPointerException();
2004-09-09 15:17:55 +04:00
}
catch(ArgumentException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
#endif // !FIRST_PASS
2003-02-27 19:41:47 +03:00
}
2005-03-03 11:20:13 +03:00
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy_primitive_8(Array src, int srcStart, Array dest, int destStart, int len)
2003-02-27 19:41:47 +03:00
{
#if !FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
checked
{
Buffer.BlockCopy(src, srcStart * 8, dest, destStart * 8, len * 8);
2004-09-09 15:17:55 +04:00
return;
}
}
catch(ArgumentNullException)
{
throw new java.lang.NullPointerException();
2004-09-09 15:17:55 +04:00
}
catch(OverflowException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
catch(ArgumentException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
#endif // !FIRST_PASS
2003-02-27 19:41:47 +03:00
}
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy_primitive_4(Array src, int srcStart, Array dest, int destStart, int len)
2003-02-27 19:41:47 +03:00
{
#if !FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
checked
{
Buffer.BlockCopy(src, srcStart * 4, dest, destStart * 4, len * 4);
2004-09-09 15:17:55 +04:00
return;
}
}
catch(ArgumentNullException)
{
throw new java.lang.NullPointerException();
2004-09-09 15:17:55 +04:00
}
catch(OverflowException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
catch(ArgumentException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
#endif // !FIRST_PASS
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy_primitive_2(Array src, int srcStart, Array dest, int destStart, int len)
2003-02-27 19:41:47 +03:00
{
#if !FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
checked
{
Buffer.BlockCopy(src, srcStart * 2, dest, destStart * 2, len * 2);
2004-09-09 15:17:55 +04:00
return;
}
}
catch(ArgumentNullException)
{
throw new java.lang.NullPointerException();
2004-09-09 15:17:55 +04:00
}
catch(OverflowException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
catch(ArgumentException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
#endif // !FIRST_PASS
2003-02-27 19:41:47 +03:00
}
2004-09-09 15:17:55 +04:00
2004-09-17 13:32:06 +04:00
[DebuggerStepThroughAttribute]
2004-09-09 15:17:55 +04:00
public static void arraycopy_primitive_1(Array src, int srcStart, Array dest, int destStart, int len)
2003-02-27 19:41:47 +03:00
{
#if !FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
Buffer.BlockCopy(src, srcStart, dest, destStart, len);
return;
}
catch(ArgumentNullException)
{
throw new java.lang.NullPointerException();
2004-09-09 15:17:55 +04:00
}
catch(OverflowException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
catch(ArgumentException)
{
throw new java.lang.ArrayIndexOutOfBoundsException();
2004-09-09 15:17:55 +04:00
}
#endif // !FIRST_PASS
2003-02-27 19:41:47 +03:00
}
2005-02-11 17:46:58 +03:00
2005-05-26 10:53:50 +04:00
[HideFromJava]
2005-02-11 17:46:58 +03:00
public static void VerboseCastFailure(RuntimeTypeHandle typeHandle, object obj)
{
#if !FIRST_PASS
Type t1 = obj.GetType();
Type t2 = Type.GetTypeFromHandle(typeHandle);
string msg;
if(t1.Assembly.FullName == t2.Assembly.FullName && t1.Assembly.Location != t2.Assembly.Location)
{
string l1 = t1.Assembly.Location;
string l2 = t2.Assembly.Location;
if(l1 == "")
{
l1 = "unknown location";
}
if(l2 == "")
{
l2 = "unknown location";
}
msg = String.Format("Object of type \"{0}\" loaded from {1} cannot be cast to \"{2}\" loaded from {3}", t1.AssemblyQualifiedName, l1, t2.AssemblyQualifiedName, l2);
}
else
{
msg = String.Format("Object of type \"{0}\" cannot be cast to \"{1}\"", t1.AssemblyQualifiedName, t2.AssemblyQualifiedName);
}
throw new java.lang.ClassCastException(msg);
#endif // !FIRST_PASS
2005-02-11 17:46:58 +03:00
}
2005-05-02 14:03:21 +04:00
public static bool SkipFinalizer()
{
#if COMPACT_FRAMEWORK || FIRST_PASS
2005-12-07 12:06:32 +03:00
return false;
#else
return Environment.HasShutdownStarted && !java.lang.Shutdown.runFinalizersOnExit;
2006-06-08 13:26:33 +04:00
#endif
}
#if COMPACT_FRAMEWORK
2006-06-08 13:26:33 +04:00
private static readonly object volatileLock = new object();
#endif
public static long VolatileRead(ref long v)
{
#if !COMPACT_FRAMEWORK
2006-06-08 13:26:33 +04:00
return Interlocked.Read(ref v);
#else
lock(volatileLock)
{
return v;
}
#endif
}
public static void VolatileWrite(ref long v, long newValue)
{
#if !COMPACT_FRAMEWORK
2006-06-08 13:26:33 +04:00
Interlocked.Exchange(ref v, newValue);
#else
lock(volatileLock)
{
v = newValue;
}
#endif
}
public static double VolatileRead(ref double v)
{
#if !COMPACT_FRAMEWORK
2006-06-08 13:26:33 +04:00
return Interlocked.CompareExchange(ref v, 0.0, 0.0);
#else
lock(volatileLock)
{
return v;
}
#endif
}
public static void VolatileWrite(ref double v, double newValue)
{
#if !COMPACT_FRAMEWORK
2006-06-08 13:26:33 +04:00
Interlocked.Exchange(ref v, newValue);
#else
lock(volatileLock)
{
v = newValue;
}
2005-12-07 12:06:32 +03:00
#endif
2005-05-02 14:03:21 +04:00
}
2003-02-27 19:41:47 +03:00
}
[StructLayout(LayoutKind.Explicit)]
public struct DoubleConverter
{
[FieldOffset(0)]
private double d;
[FieldOffset(0)]
private long l;
public static long ToLong(double value, ref DoubleConverter converter)
{
converter.d = value;
return converter.l;
}
public static double ToDouble(long value, ref DoubleConverter converter)
{
converter.l = value;
return converter.d;
}
}
[StructLayout(LayoutKind.Explicit)]
public struct FloatConverter
{
[FieldOffset(0)]
private float f;
[FieldOffset(0)]
private int i;
public static int ToInt(float value, ref FloatConverter converter)
{
converter.f = value;
return converter.i;
}
public static float ToFloat(int value, ref FloatConverter converter)
{
converter.i = value;
return converter.f;
}
}
2002-12-18 19:00:25 +03:00
}