2014-08-13 10:39:27 +01:00
/ *
2015-08-26 07:17:56 -04:00
Copyright ( C ) 2002 - 2015 Jeroen Frijters
2014-08-13 10:39:27 +01: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 ;
using System.Reflection ;
using System.Diagnostics ;
using System.Threading ;
using IKVM.Attributes ;
using IKVM.Internal ;
using System.Runtime.InteropServices ;
namespace IKVM.Runtime
{
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 ;
}
// this method is called from <GhostType>.CastArray()
[HideFromJava]
internal static void ThrowClassCastException ( object obj , RuntimeTypeHandle typeHandle , int rank )
{
#if ! FIRST_PASS
System . Text . StringBuilder sb = new System . Text . StringBuilder ( ) ;
sb . Append ( ikvm . runtime . Util . getClassFromObject ( obj ) . getName ( ) ) . Append ( " cannot be cast to " )
. Append ( '[' , rank ) . Append ( 'L' ) . Append ( ikvm . runtime . Util . getClassFromTypeHandle ( typeHandle ) . getName ( ) ) . Append ( ';' ) ;
throw new java . lang . ClassCastException ( sb . ToString ( ) ) ;
#endif
}
}
public static class ByteCodeHelper
{
[DebuggerStepThroughAttribute]
public static object multianewarray ( RuntimeTypeHandle typeHandle , int [ ] lengths )
{
for ( int i = 0 ; i < lengths . Length ; i + + )
{
if ( lengths [ i ] < 0 )
{
#if ! FIRST_PASS
throw new java . lang . NegativeArraySizeException ( ) ;
#endif
}
}
return MultianewarrayHelper ( Type . GetTypeFromHandle ( typeHandle ) . GetElementType ( ) , lengths , 0 ) ;
}
private static object MultianewarrayHelper ( Type elemType , int [ ] lengths , int index )
{
object o = Array . CreateInstance ( elemType , lengths [ index + + ] ) ;
if ( index < lengths . Length )
{
elemType = elemType . GetElementType ( ) ;
object [ ] a = ( object [ ] ) o ;
for ( int i = 0 ; i < a . Length ; i + + )
{
a [ i ] = MultianewarrayHelper ( elemType , lengths , index ) ;
}
}
return o ;
}
[DebuggerStepThroughAttribute]
public static object multianewarray_ghost ( RuntimeTypeHandle typeHandle , int [ ] lengths )
{
Type type = Type . GetTypeFromHandle ( typeHandle ) ;
int rank = 0 ;
while ( ReflectUtil . IsVector ( type ) )
{
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 ;
}
[DebuggerStepThroughAttribute]
2015-08-26 07:17:56 -04:00
public static object DynamicMultianewarray ( int [ ] lengths , java . lang . Class clazz )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if FIRST_PASS
return null ;
#else
2014-08-13 10:39:27 +01:00
Profiler . Count ( "DynamicMultianewarray" ) ;
2015-08-26 07:17:56 -04:00
TypeWrapper wrapper = TypeWrapper . FromClass ( clazz ) ;
object obj = multianewarray ( wrapper . TypeAsArrayType . TypeHandle , lengths ) ;
if ( wrapper . IsGhostArray )
{
GhostTag . SetTag ( obj , wrapper ) ;
}
return obj ;
#endif
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
2015-08-26 07:17:56 -04:00
public static object DynamicNewarray ( int length , java . lang . Class clazz )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if FIRST_PASS
return null ;
#else
2014-08-13 10:39:27 +01:00
Profiler . Count ( "DynamicNewarray" ) ;
if ( length < 0 )
{
throw new java . lang . NegativeArraySizeException ( ) ;
}
2015-08-26 07:17:56 -04:00
TypeWrapper wrapper = TypeWrapper . FromClass ( clazz ) ;
Array obj = Array . CreateInstance ( wrapper . TypeAsArrayType , length ) ;
if ( wrapper . IsGhost | | wrapper . IsGhostArray )
{
GhostTag . SetTag ( obj , wrapper . MakeArrayType ( 1 ) ) ;
}
return obj ;
#endif
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
2015-08-26 07:17:56 -04:00
public static void DynamicAastore ( object arrayref , int index , object val )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if ! FIRST_PASS
2014-08-13 10:39:27 +01:00
Profiler . Count ( "DynamicAastore" ) ;
( ( Array ) arrayref ) . SetValue ( val , index ) ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
2015-08-26 07:17:56 -04:00
public static object DynamicAaload ( object arrayref , int index )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if FIRST_PASS
return null ;
#else
2014-08-13 10:39:27 +01:00
Profiler . Count ( "DynamicAaload" ) ;
return ( ( Array ) arrayref ) . GetValue ( index ) ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
// the sole purpose of this method is to check whether the clazz can be instantiated (but not to actually do it)
[DebuggerStepThroughAttribute]
2015-08-26 07:17:56 -04:00
public static void DynamicNewCheckOnly ( java . lang . Class clazz )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if ! FIRST_PASS
2014-08-13 10:39:27 +01:00
Profiler . Count ( "DynamicNewCheckOnly" ) ;
2015-08-26 07:17:56 -04:00
TypeWrapper wrapper = TypeWrapper . FromClass ( clazz ) ;
2014-08-13 10:39:27 +01:00
if ( wrapper . IsAbstract )
{
2015-08-26 07:17:56 -04:00
throw new java . lang . InstantiationError ( wrapper . Name ) ;
2014-08-13 10:39:27 +01:00
}
wrapper . RunClassInit ( ) ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
private static TypeWrapper LoadTypeWrapper ( string clazz , ikvm . @internal . CallerID callerId )
{
#if FIRST_PASS
return null ;
#else
try
{
TypeWrapper context = TypeWrapper . FromClass ( callerId . getCallerClass ( ) ) ;
TypeWrapper wrapper = ClassLoaderWrapper . FromCallerID ( callerId ) . LoadClassByDottedName ( clazz ) ;
2015-08-26 07:17:56 -04:00
java . lang . ClassLoader loader = callerId . getCallerClassLoader ( ) ;
if ( loader ! = null )
{
loader . checkPackageAccess ( wrapper . ClassObject , callerId . getCallerClass ( ) . pd ) ;
}
2014-08-13 10:39:27 +01:00
if ( ! wrapper . IsAccessibleFrom ( context ) )
{
throw new java . lang . IllegalAccessError ( "Try to access class " + wrapper . Name + " from class " + context . Name ) ;
}
wrapper . Finish ( ) ;
return wrapper ;
}
catch ( RetargetableJavaException x )
{
throw x . ToJava ( ) ;
}
#endif
}
[DebuggerStepThroughAttribute]
public static java . lang . Class DynamicClassLiteral ( string clazz , ikvm . @internal . CallerID callerId )
{
2015-08-26 07:17:56 -04:00
#if FIRST_PASS
return null ;
#else
2014-08-13 10:39:27 +01:00
Profiler . Count ( "DynamicClassLiteral" ) ;
return LoadTypeWrapper ( clazz , callerId ) . ClassObject ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
2015-08-26 07:17:56 -04:00
public static object DynamicCast ( object obj , java . lang . Class clazz )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if FIRST_PASS
return null ;
#else
Debug . Assert ( obj ! = null ) ;
2014-08-13 10:39:27 +01:00
Profiler . Count ( "DynamicCast" ) ;
2015-08-26 07:17:56 -04:00
if ( ! DynamicInstanceOf ( obj , clazz ) )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
throw new java . lang . ClassCastException ( NativeCode . ikvm . runtime . Util . GetTypeWrapperFromObject ( obj ) . Name + " cannot be cast to " + clazz . getName ( ) ) ;
2014-08-13 10:39:27 +01:00
}
return obj ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
2015-08-26 07:17:56 -04:00
public static bool DynamicInstanceOf ( object obj , java . lang . Class clazz )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if FIRST_PASS
return false ;
#else
Debug . Assert ( obj ! = null ) ;
2014-08-13 10:39:27 +01:00
Profiler . Count ( "DynamicInstanceOf" ) ;
2015-08-26 07:17:56 -04:00
TypeWrapper tw = TypeWrapper . FromClass ( clazz ) ;
// we have to mimick the bytecode behavior, which allows these .NET-isms to show through
if ( tw . TypeAsBaseType = = typeof ( Array ) )
{
return obj is Array ;
}
if ( tw . TypeAsBaseType = = typeof ( string ) )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return obj is string ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( tw . TypeAsBaseType = = typeof ( IComparable ) )
{
return obj is IComparable ;
}
return tw . IsInstance ( obj ) ;
#endif
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThrough]
public static java . lang . invoke . MethodType DynamicLoadMethodType ( ref java . lang . invoke . MethodType cache , string sig , ikvm . @internal . CallerID callerID )
{
if ( cache = = null )
{
DynamicLoadMethodTypeImpl ( ref cache , sig , callerID ) ;
}
return cache ;
}
private static void DynamicLoadMethodTypeImpl ( ref java . lang . invoke . MethodType cache , string sig , ikvm . @internal . CallerID callerID )
{
#if ! FIRST_PASS
try
{
ClassLoaderWrapper loader = ClassLoaderWrapper . FromCallerID ( callerID ) ;
2015-08-26 07:17:56 -04:00
TypeWrapper [ ] args = loader . ArgTypeWrapperListFromSig ( sig , LoadMode . LoadOrThrow ) ;
2014-08-13 10:39:27 +01:00
java . lang . Class [ ] ptypes = new java . lang . Class [ args . Length ] ;
for ( int i = 0 ; i < ptypes . Length ; i + + )
{
ptypes [ i ] = args [ i ] . ClassObject ;
}
2015-08-26 07:17:56 -04:00
Interlocked . CompareExchange ( ref cache , java . lang . invoke . MethodType . methodType ( loader . RetTypeWrapperFromSig ( sig , LoadMode . LoadOrThrow ) . ClassObject , ptypes ) , null ) ;
2014-08-13 10:39:27 +01:00
}
catch ( RetargetableJavaException x )
{
throw x . ToJava ( ) ;
}
#endif
}
[DebuggerStepThrough]
public static java . lang . invoke . MethodHandle DynamicLoadMethodHandle ( ref java . lang . invoke . MethodHandle cache , int kind , string clazz , string name , string sig , ikvm . @internal . CallerID callerID )
{
if ( cache = = null )
{
Interlocked . CompareExchange ( ref cache , DynamicLoadMethodHandleImpl ( kind , clazz , name , sig , callerID ) , null ) ;
}
return cache ;
}
private static java . lang . invoke . MethodHandle DynamicLoadMethodHandleImpl ( int kind , string clazz , string name , string sig , ikvm . @internal . CallerID callerID )
{
#if FIRST_PASS
return null ;
#else
java . lang . Class refc = LoadTypeWrapper ( clazz , callerID ) . ClassObject ;
try
{
switch ( ( ClassFile . RefKind ) kind )
{
case ClassFile . RefKind . getStatic :
case ClassFile . RefKind . putStatic :
case ClassFile . RefKind . getField :
case ClassFile . RefKind . putField :
2015-08-26 07:17:56 -04:00
java . lang . Class type = ClassLoaderWrapper . FromCallerID ( callerID ) . FieldTypeWrapperFromSig ( sig , LoadMode . LoadOrThrow ) . ClassObject ;
return java . lang . invoke . MethodHandleNatives . linkMethodHandleConstant ( callerID . getCallerClass ( ) , kind , refc , name , type ) ;
2014-08-13 10:39:27 +01:00
default :
java . lang . invoke . MethodType mt = null ;
DynamicLoadMethodType ( ref mt , sig , callerID ) ;
2015-08-26 07:17:56 -04:00
// HACK linkMethodHandleConstant is broken for MethodHandle.invoke[Exact]
if ( kind = = ( int ) ClassFile . RefKind . invokeVirtual & & refc = = CoreClasses . java . lang . invoke . MethodHandle . Wrapper . ClassObject )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
switch ( name )
{
case "invokeExact" :
return java . lang . invoke . MethodHandles . exactInvoker ( mt ) ;
case "invoke" :
return java . lang . invoke . MethodHandles . invoker ( mt ) ;
}
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
return java . lang . invoke . MethodHandleNatives . linkMethodHandleConstant ( callerID . getCallerClass ( ) , kind , refc , name , mt ) ;
2014-08-13 10:39:27 +01:00
}
}
catch ( RetargetableJavaException x )
{
throw x . ToJava ( ) ;
}
#endif
}
[DebuggerStepThrough]
public static T DynamicBinderMemberLookup < T > ( int kind , string clazz , string name , string sig , ikvm . @internal . CallerID callerID )
where T : class /* delegate */
{
#if FIRST_PASS
return null ;
#else
try
{
java . lang . invoke . MethodHandle mh = DynamicLoadMethodHandleImpl ( kind , clazz , name , sig , callerID ) ;
2015-08-26 07:17:56 -04:00
return GetDelegateForInvokeExact < T > ( java . lang . invoke . MethodHandles . explicitCastArguments ( mh , MethodHandleUtil . GetDelegateMethodType ( typeof ( T ) ) ) ) ;
2014-08-13 10:39:27 +01:00
}
catch ( java . lang . IncompatibleClassChangeError x )
{
if ( x . getCause ( ) is java . lang . NoSuchMethodException )
{
throw new java . lang . NoSuchMethodError ( x . getCause ( ) . Message ) ;
}
if ( x . getCause ( ) is java . lang . NoSuchFieldException )
{
throw new java . lang . NoSuchFieldError ( x . getCause ( ) . Message ) ;
}
if ( x . getCause ( ) is java . lang . IllegalAccessException )
{
throw new java . lang . IllegalAccessError ( x . getCause ( ) . Message ) ;
}
throw ;
}
#endif
}
[DebuggerStepThrough]
public static Delegate DynamicCreateDelegate ( object obj , Type delegateType , string name , string sig )
{
2015-08-26 07:17:56 -04:00
#if FIRST_PASS
return null ;
#else
2014-08-13 10:39:27 +01:00
TypeWrapper tw = TypeWrapper . FromClass ( ikvm . runtime . Util . getClassFromObject ( obj ) ) ;
MethodWrapper mw = tw . GetMethodWrapper ( name , sig , true ) ;
if ( mw = = null | | mw . IsStatic | | ! mw . IsPublic )
{
2015-08-26 07:17:56 -04:00
#if NO_REF_EMIT
java . lang . invoke . MethodType methodType = MethodHandleUtil . GetDelegateMethodType ( delegateType ) ;
if ( methodType . parameterCount ( ) > MethodHandleUtil . MaxArity )
{
throw new NotImplementedException ( ) ;
}
java . lang . invoke . MethodHandle exception = java . lang . invoke . MethodHandles . publicLookup ( )
. findConstructor ( mw = = null | | mw . IsStatic ? typeof ( java . lang . AbstractMethodError ) : typeof ( java . lang . IllegalAccessError ) ,
java . lang . invoke . MethodType . methodType ( typeof ( void ) , typeof ( string ) ) )
. bindTo ( tw . Name + ".Invoke" + sig ) ;
return Delegate . CreateDelegate ( delegateType ,
java . lang . invoke . MethodHandles . dropArguments (
java . lang . invoke . MethodHandles . foldArguments ( java . lang . invoke . MethodHandles . throwException ( methodType . returnType ( ) , exception . type ( ) . returnType ( ) ) , exception ) ,
0 , methodType . parameterArray ( ) ) . vmtarget , "Invoke" ) ;
#else
2014-08-13 10:39:27 +01:00
MethodInfo invoke = delegateType . GetMethod ( "Invoke" ) ;
ParameterInfo [ ] parameters = invoke . GetParameters ( ) ;
Type [ ] parameterTypes = new Type [ parameters . Length + 1 ] ;
parameterTypes [ 0 ] = typeof ( object ) ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
parameterTypes [ i + 1 ] = parameters [ i ] . ParameterType ;
}
System . Reflection . Emit . DynamicMethod dm = new System . Reflection . Emit . DynamicMethod ( "Invoke" , invoke . ReturnType , parameterTypes ) ;
CodeEmitter ilgen = CodeEmitter . Create ( dm ) ;
ilgen . Emit ( System . Reflection . Emit . OpCodes . Ldstr , tw . Name + ".Invoke" + sig ) ;
ClassLoaderWrapper . GetBootstrapClassLoader ( )
. LoadClassByDottedName ( mw = = null | | mw . IsStatic ? "java.lang.AbstractMethodError" : "java.lang.IllegalAccessError" )
. GetMethodWrapper ( "<init>" , "(Ljava.lang.String;)V" , false )
. EmitNewobj ( ilgen ) ;
ilgen . Emit ( System . Reflection . Emit . OpCodes . Throw ) ;
ilgen . DoEmit ( ) ;
return dm . CreateDelegate ( delegateType , obj ) ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
else
{
mw . ResolveMethod ( ) ;
return Delegate . CreateDelegate ( delegateType , obj , ( MethodInfo ) mw . GetMethod ( ) ) ;
}
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
[DebuggerStepThrough]
public static ikvm . @internal . CallerID DynamicCallerID ( object capability )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return ( ( DynamicCallerIDProvider ) capability ) . GetCallerID ( ) ;
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThrough]
2015-08-26 07:17:56 -04:00
public static java . lang . invoke . MethodHandle DynamicEraseInvokeExact ( java . lang . invoke . MethodHandle mh , java . lang . invoke . MethodType expected , java . lang . invoke . MethodType target )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if FIRST_PASS
2014-08-13 10:39:27 +01:00
return null ;
2015-08-26 07:17:56 -04:00
#else
if ( mh . type ( ) ! = expected )
{
throw new java . lang . invoke . WrongMethodTypeException ( ) ;
}
return java . lang . invoke . MethodHandles . explicitCastArguments ( mh , target ) ;
#endif
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
public static int f2i ( float f )
{
2015-08-26 07:17:56 -04:00
if ( f > int . MinValue & & f < int . MaxValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return ( int ) f ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( f < = int . MinValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return int . MinValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( f > = int . MaxValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return int . MaxValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
return 0 ;
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
public static long f2l ( float f )
{
2015-08-26 07:17:56 -04:00
if ( f > long . MinValue & & f < long . MaxValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return ( long ) f ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( f < = long . MinValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return long . MinValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( f > = long . MaxValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return long . MaxValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
return 0 ;
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
public static int d2i ( double d )
{
2015-08-26 07:17:56 -04:00
if ( d > int . MinValue & & d < int . MaxValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return ( int ) d ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( d < = int . MinValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return int . MinValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( d > = int . MaxValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return int . MaxValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
return 0 ;
2014-08-13 10:39:27 +01:00
}
[DebuggerStepThroughAttribute]
public static long d2l ( double d )
{
2015-08-26 07:17:56 -04:00
if ( d > long . MinValue & & d < long . MaxValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return ( long ) d ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( d < = long . MinValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return long . MinValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
if ( d > = long . MaxValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return long . MaxValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
return 0 ;
2014-08-13 10:39:27 +01:00
}
// This is used by static JNI and synchronized methods that need a class object
[DebuggerStepThroughAttribute]
public static object GetClassFromTypeHandle ( RuntimeTypeHandle typeHandle )
{
return NativeCode . ikvm . runtime . Util . getClassFromTypeHandle ( typeHandle ) ;
}
[DebuggerStepThroughAttribute]
public static void arraycopy ( object src , int srcStart , object dest , int destStart , int len )
{
#if ! FIRST_PASS
// 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 )
{
try
{
arraycopy_fast ( ( Array ) src , srcStart , ( Array ) dest , destStart , len ) ;
return ;
}
catch ( InvalidCastException )
{
throw new java . lang . ArrayStoreException ( ) ;
}
}
else if ( src = = null | | dest = = null )
{
throw new java . lang . NullPointerException ( ) ;
}
else if ( len < 0 )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
else
{
object [ ] src1 = src as object [ ] ;
object [ ] dst1 = dest as object [ ] ;
if ( src1 ! = null & & dst1 ! = null )
{
// for small copies, don't bother comparing the types as this is relatively expensive
if ( len > 50 & & src . GetType ( ) = = dest . GetType ( ) )
{
arraycopy_fast ( src1 , srcStart , dst1 , destStart , len ) ;
return ;
}
else
{
for ( ; len > 0 ; len - - )
{
// NOTE we don't need to catch ArrayTypeMismatchException & IndexOutOfRangeException, because
// they automatically get converted to the Java equivalents anyway.
dst1 [ destStart + + ] = src1 [ srcStart + + ] ;
}
return ;
}
}
else if ( src . GetType ( ) ! = dest . GetType ( ) & &
( IsPrimitiveArrayType ( src . GetType ( ) ) | | IsPrimitiveArrayType ( dest . GetType ( ) ) ) )
{
// we don't want to allow copying a primitive into an object array!
throw new java . lang . ArrayStoreException ( ) ;
}
else
{
try
{
arraycopy_fast ( ( Array ) src , srcStart , ( Array ) dest , destStart , len ) ;
return ;
}
catch ( InvalidCastException )
{
throw new java . lang . ArrayStoreException ( ) ;
}
}
}
#endif // !FIRST_PASS
}
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
try
{
Array . Copy ( src , srcStart , dest , destStart , len ) ;
}
catch ( ArgumentNullException )
{
throw new java . lang . NullPointerException ( ) ;
}
catch ( ArgumentException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
#endif // !FIRST_PASS
}
[DebuggerStepThroughAttribute]
public static void arraycopy_primitive_8 ( Array src , int srcStart , Array dest , int destStart , int len )
{
#if ! FIRST_PASS
try
{
checked
{
Buffer . BlockCopy ( src , srcStart * 8 , dest , destStart * 8 , len * 8 ) ;
return ;
}
}
catch ( ArgumentNullException )
{
throw new java . lang . NullPointerException ( ) ;
}
catch ( OverflowException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( ArgumentException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
#endif // !FIRST_PASS
}
[DebuggerStepThroughAttribute]
public static void arraycopy_primitive_4 ( Array src , int srcStart , Array dest , int destStart , int len )
{
#if ! FIRST_PASS
try
{
checked
{
Buffer . BlockCopy ( src , srcStart * 4 , dest , destStart * 4 , len * 4 ) ;
return ;
}
}
catch ( ArgumentNullException )
{
throw new java . lang . NullPointerException ( ) ;
}
catch ( OverflowException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( ArgumentException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
#endif // !FIRST_PASS
}
[DebuggerStepThroughAttribute]
public static void arraycopy_primitive_2 ( Array src , int srcStart , Array dest , int destStart , int len )
{
#if ! FIRST_PASS
try
{
checked
{
Buffer . BlockCopy ( src , srcStart * 2 , dest , destStart * 2 , len * 2 ) ;
return ;
}
}
catch ( ArgumentNullException )
{
throw new java . lang . NullPointerException ( ) ;
}
catch ( OverflowException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( ArgumentException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
#endif // !FIRST_PASS
}
[DebuggerStepThroughAttribute]
public static void arraycopy_primitive_1 ( Array src , int srcStart , Array dest , int destStart , int len )
{
#if ! FIRST_PASS
try
{
Buffer . BlockCopy ( src , srcStart , dest , destStart , len ) ;
return ;
}
catch ( ArgumentNullException )
{
throw new java . lang . NullPointerException ( ) ;
}
catch ( OverflowException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
catch ( ArgumentException )
{
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
}
#endif // !FIRST_PASS
}
[HideFromJava]
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
}
public static bool SkipFinalizer ( )
{
#if FIRST_PASS
return false ;
#else
return Environment . HasShutdownStarted & & ! java . lang . Shutdown . runFinalizersOnExit ;
#endif
}
public static long VolatileRead ( ref long v )
{
2015-08-26 07:17:56 -04:00
#if NO_REF_EMIT & & ! FIRST_PASS
lock ( VolatileLongDoubleFieldWrapper . lockObject )
{
return v ;
}
#else
2014-08-13 10:39:27 +01:00
return Interlocked . Read ( ref v ) ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
public static void VolatileWrite ( ref long v , long newValue )
{
2015-08-26 07:17:56 -04:00
#if NO_REF_EMIT & & ! FIRST_PASS
lock ( VolatileLongDoubleFieldWrapper . lockObject )
{
v = newValue ;
}
#else
2014-08-13 10:39:27 +01:00
Interlocked . Exchange ( ref v , newValue ) ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
public static double VolatileRead ( ref double v )
{
2015-08-26 07:17:56 -04:00
#if NO_REF_EMIT & & ! FIRST_PASS
lock ( VolatileLongDoubleFieldWrapper . lockObject )
{
return v ;
}
#else
2014-08-13 10:39:27 +01:00
return Interlocked . CompareExchange ( ref v , 0.0 , 0.0 ) ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
public static void VolatileWrite ( ref double v , double newValue )
{
2015-08-26 07:17:56 -04:00
#if NO_REF_EMIT & & ! FIRST_PASS
lock ( VolatileLongDoubleFieldWrapper . lockObject )
{
v = newValue ;
}
#else
2014-08-13 10:39:27 +01:00
Interlocked . Exchange ( ref v , newValue ) ;
2015-08-26 07:17:56 -04:00
#endif
2014-08-13 10:39:27 +01:00
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public static void InitializeModule ( Module module )
{
Assembly asm = Assembly . GetCallingAssembly ( ) ;
if ( module . Assembly ! = asm )
{
throw new ArgumentOutOfRangeException ( ) ;
}
object classLoader = AssemblyClassLoader . FromAssembly ( asm ) . GetJavaClassLoader ( ) ;
Action < Module > init = ( Action < Module > ) Delegate . CreateDelegate ( typeof ( Action < Module > ) , classLoader , "InitializeModule" , false , false ) ;
if ( init ! = null )
{
init ( module ) ;
}
}
public static T GetDotNetEnumField < T > ( string name )
#if ! FIRST_PASS
where T : java . lang . Enum
#endif
{
#if FIRST_PASS
return default ( T ) ;
#else
try
{
return ( T ) java . lang . Enum . valueOf ( ikvm . @internal . ClassLiteral < T > . Value , name ) ;
}
catch ( java . lang . IllegalArgumentException )
{
throw new java . lang . NoSuchFieldError ( ikvm . @internal . ClassLiteral < T > . Value . getName ( ) + "." + name ) ;
}
#endif
}
[Flags]
public enum MapFlags
{
None = 0 ,
NoRemapping = 1 ,
Unused = 2 ,
}
[HideFromJava]
public static T MapException < T > ( Exception x , MapFlags mode ) where T : Exception
{
return ExceptionHelper . MapException < T > ( x , ( mode & MapFlags . NoRemapping ) = = 0 , ( mode & MapFlags . Unused ) ! = 0 ) ;
}
2015-08-26 07:17:56 -04:00
[HideFromJava]
public static Exception DynamicMapException ( Exception x , MapFlags mode , java . lang . Class exceptionClass )
{
#if FIRST_PASS
return null ;
#else
TypeWrapper exceptionTypeWrapper = TypeWrapper . FromClass ( exceptionClass ) ;
mode & = ~ MapFlags . NoRemapping ;
if ( exceptionTypeWrapper . IsSubTypeOf ( CoreClasses . cli . System . Exception . Wrapper ) )
{
mode | = MapFlags . NoRemapping ;
}
Type exceptionType = exceptionTypeWrapper = = CoreClasses . java . lang . Throwable . Wrapper ? typeof ( System . Exception ) : exceptionTypeWrapper . TypeAsBaseType ;
return ( Exception ) ByteCodeHelperMethods . mapException . MakeGenericMethod ( exceptionType ) . Invoke ( null , new object [ ] { x , mode } ) ;
#endif
}
2014-08-13 10:39:27 +01:00
public static T GetDelegateForInvokeExact < T > ( global :: java . lang . invoke . MethodHandle h )
where T : class
{
#if FIRST_PASS
return null ;
#else
2015-08-26 07:17:56 -04:00
T del = h . _invokeExactDelegate as T ;
2014-08-13 10:39:27 +01:00
if ( del = = null )
{
2015-08-26 07:17:56 -04:00
del = MethodHandleUtil . GetDelegateForInvokeExact < T > ( h ) ;
2014-08-13 10:39:27 +01:00
}
return del ;
#endif
}
2015-08-26 07:17:56 -04:00
public static T GetDelegateForInvoke < T > ( global :: java . lang . invoke . MethodHandle h , java . lang . invoke . MethodType realType , ref InvokeCache < T > cache )
2014-08-13 10:39:27 +01:00
where T : class
{
#if FIRST_PASS
return null ;
#else
2015-08-26 07:17:56 -04:00
T del ;
if ( cache . Type = = h . type ( ) & & ( del = ( h . isVarargsCollector ( ) ? cache . varArg : cache . fixedArg ) ) ! = null )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return del ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
del = h . form . vmentry . vmtarget as T ;
2014-08-13 10:39:27 +01:00
if ( del = = null )
{
global :: java . lang . invoke . MethodHandle adapter = global :: java . lang . invoke . MethodHandles . exactInvoker ( h . type ( ) ) ;
if ( h . isVarargsCollector ( ) )
{
adapter = adapter . asVarargsCollector ( h . type ( ) . parameterType ( h . type ( ) . parameterCount ( ) - 1 ) ) ;
}
2015-08-26 07:17:56 -04:00
// if realType is set, the delegate contains erased unloadable types
if ( realType ! = null )
{
adapter = adapter . asType ( realType . insertParameterTypes ( 0 , ikvm . @internal . ClassLiteral < java . lang . invoke . MethodHandle > . Value ) ) . asFixedArity ( ) ;
}
adapter = adapter . asType ( MethodHandleUtil . GetDelegateMethodType ( typeof ( T ) ) ) ;
del = GetDelegateForInvokeExact < T > ( adapter ) ;
if ( cache . TrySetType ( h . type ( ) ) )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
if ( h . isVarargsCollector ( ) )
{
cache . varArg = del ;
}
else
{
cache . fixedArg = del ;
}
2014-08-13 10:39:27 +01:00
}
}
return del ;
#endif
}
2015-08-26 07:17:56 -04:00
public static T GetDelegateForInvokeBasic < T > ( java . lang . invoke . MethodHandle h )
where T : class
2014-08-13 10:39:27 +01:00
{
#if FIRST_PASS
return null ;
#else
2015-08-26 07:17:56 -04:00
T del = h . form . vmentry . vmtarget as T ;
if ( del = = null )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
del = MethodHandleUtil . GetVoidAdapter ( h . form . vmentry ) as T ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
return del ;
2014-08-13 10:39:27 +01:00
#endif
2015-08-26 07:17:56 -04:00
}
2014-08-13 10:39:27 +01:00
2015-08-26 07:17:56 -04:00
public static java . lang . invoke . MethodType LoadMethodType < T > ( )
where T : class // Delegate
2014-08-13 10:39:27 +01:00
{
#if FIRST_PASS
return null ;
#else
2015-08-26 07:17:56 -04:00
return MethodHandleUtil . GetDelegateMethodType ( typeof ( T ) ) ;
2014-08-13 10:39:27 +01:00
#endif
}
[HideFromJava]
public static void LinkIndyCallSite < T > ( ref IndyCallSite < T > site , java . lang . invoke . CallSite cs , Exception x )
where T : class // Delegate
{
#if ! FIRST_PASS
2015-08-26 07:17:56 -04:00
// when a CallSite is first constructed, it doesn't call MethodHandleNatives.setCallSiteTargetNormal(),
// so we have to check if we need to initialize it here (i.e. attach an IndyCallSite<T> to it)
if ( cs ! = null )
{
if ( cs . ics = = null )
{
Java_java_lang_invoke_MethodHandleNatives . InitializeCallSite ( cs ) ;
}
lock ( cs . ics )
{
cs . ics . SetTarget ( cs . target ) ;
}
}
2014-08-13 10:39:27 +01:00
IndyCallSite < T > ics ;
if ( x ! = null | | cs = = null | | ( ics = cs . ics as IndyCallSite < T > ) = = null )
{
x = MapException < Exception > ( x ? ? ( cs = = null
? ( Exception ) new java . lang . ClassCastException ( "bootstrap method failed to produce a CallSite" )
: new java . lang . invoke . WrongMethodTypeException ( ) ) , MapFlags . None ) ;
java . lang . invoke . MethodType type = LoadMethodType < T > ( ) ;
2015-08-26 07:17:56 -04:00
java . lang . invoke . MethodHandle exc = x is java . lang . BootstrapMethodError
? java . lang . invoke . MethodHandles . constant ( typeof ( java . lang . BootstrapMethodError ) , x )
: java . lang . invoke . MethodHandles . publicLookup ( ) . findConstructor ( typeof ( java . lang . BootstrapMethodError ) , java . lang . invoke . MethodType . methodType ( typeof ( void ) , typeof ( string ) , typeof ( Exception ) ) )
. bindTo ( "call site initialization exception" ) . bindTo ( x ) ;
ics = new IndyCallSite < T > ( ) ;
( ( IIndyCallSite ) ics ) . SetTarget (
2014-08-13 10:39:27 +01:00
java . lang . invoke . MethodHandles . dropArguments (
java . lang . invoke . MethodHandles . foldArguments (
java . lang . invoke . MethodHandles . throwException ( type . returnType ( ) , typeof ( java . lang . BootstrapMethodError ) ) ,
2015-08-26 07:17:56 -04:00
exc ) ,
0 , type . parameterArray ( ) ) ) ;
2014-08-13 10:39:27 +01:00
}
IndyCallSite < T > curr = site ;
if ( curr . IsBootstrap )
{
Interlocked . CompareExchange ( ref site , ics , curr ) ;
}
#endif
}
[HideFromJava]
2015-08-26 07:17:56 -04:00
public static void DynamicLinkIndyCallSite < T > ( ref IndyCallSite < T > site , java . lang . invoke . CallSite cs , Exception x , string signature , ikvm . @internal . CallerID callerID )
where T : class // Delegate
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if ! FIRST_PASS
// when a CallSite is first constructed, it doesn't call MethodHandleNatives.setCallSiteTargetNormal(),
// so we have to check if we need to initialize it here (i.e. attach an IndyCallSite<T> to it)
if ( cs ! = null )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
if ( cs . ics = = null )
{
Java_java_lang_invoke_MethodHandleNatives . InitializeCallSite ( cs ) ;
}
lock ( cs . ics )
{
cs . ics . SetTarget ( cs . target ) ;
}
}
java . lang . invoke . MethodType typeCache = null ;
IndyCallSite < T > ics ;
if ( x ! = null | | cs = = null | | cs . type ( ) ! = DynamicLoadMethodType ( ref typeCache , signature , callerID ) )
{
x = MapException < Exception > ( x ? ? ( cs = = null
? ( Exception ) new java . lang . ClassCastException ( "bootstrap method failed to produce a CallSite" )
: new java . lang . invoke . WrongMethodTypeException ( ) ) , MapFlags . None ) ;
java . lang . invoke . MethodType type = LoadMethodType < T > ( ) ;
java . lang . invoke . MethodHandle exc = x is java . lang . BootstrapMethodError
? java . lang . invoke . MethodHandles . constant ( typeof ( java . lang . BootstrapMethodError ) , x )
: java . lang . invoke . MethodHandles . publicLookup ( ) . findConstructor ( typeof ( java . lang . BootstrapMethodError ) , java . lang . invoke . MethodType . methodType ( typeof ( void ) , typeof ( string ) , typeof ( Exception ) ) )
. bindTo ( "call site initialization exception" ) . bindTo ( x ) ;
ics = new IndyCallSite < T > ( ) ;
( ( IIndyCallSite ) ics ) . SetTarget (
java . lang . invoke . MethodHandles . dropArguments (
java . lang . invoke . MethodHandles . foldArguments (
java . lang . invoke . MethodHandles . throwException ( type . returnType ( ) , typeof ( java . lang . BootstrapMethodError ) ) ,
exc ) ,
0 , type . parameterArray ( ) ) ) ;
}
else
{
ics = new IndyCallSite < T > ( ) ;
( ( IIndyCallSite ) ics ) . SetTarget ( cs . dynamicInvoker ( ) . asType ( LoadMethodType < T > ( ) ) ) ;
}
IndyCallSite < T > curr = site ;
if ( curr . IsBootstrap )
{
Interlocked . CompareExchange ( ref site , ics , curr ) ;
2014-08-13 10:39:27 +01:00
}
#endif
2015-08-26 07:17:56 -04:00
}
}
interface IIndyCallSite
{
void SetTarget ( java . lang . invoke . MethodHandle mh ) ;
2014-08-13 10:39:27 +01:00
}
public sealed class IndyCallSite < T >
2015-08-26 07:17:56 -04:00
: IIndyCallSite
2014-08-13 10:39:27 +01:00
where T : class // Delegate
{
internal readonly bool IsBootstrap ;
private volatile T target ;
internal IndyCallSite ( )
{
}
internal IndyCallSite ( T target , bool bootstrap )
{
this . IsBootstrap = bootstrap ;
this . target = target ;
}
2015-08-26 07:17:56 -04:00
void IIndyCallSite . SetTarget ( java . lang . invoke . MethodHandle mh )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
#if ! FIRST_PASS
target = ByteCodeHelper . GetDelegateForInvokeExact < T > ( mh ) ;
2014-08-13 10:39:27 +01:00
#endif
2015-08-26 07:17:56 -04:00
}
2014-08-13 10:39:27 +01:00
public static IndyCallSite < T > CreateBootstrap ( T bootstrap )
{
return new IndyCallSite < T > ( bootstrap , true ) ;
}
public T GetTarget ( )
{
return target ;
}
}
public struct InvokeCache < T >
where T : class
{
2015-08-26 07:17:56 -04:00
#if CLASSGC
private WeakReference weakRef ;
internal java . lang . invoke . MethodType Type
{
get { return weakRef = = null ? null : ( java . lang . invoke . MethodType ) weakRef . Target ; }
}
internal bool TrySetType ( java . lang . invoke . MethodType newType )
{
if ( weakRef = = null )
{
return Interlocked . CompareExchange ( ref weakRef , new WeakReference ( newType ) , null ) = = null ;
}
return Type = = newType ;
}
#else
private java . lang . invoke . MethodType type ;
internal java . lang . invoke . MethodType Type
{
get { return type ; }
}
internal bool TrySetType ( java . lang . invoke . MethodType newType )
{
Interlocked . CompareExchange ( ref type , newType , null ) ;
return type = = newType ;
}
#endif
internal T fixedArg ;
internal T varArg ;
2014-08-13 10:39:27 +01: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 ;
}
}
public struct MHA < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 >
{
public T1 t1 ;
public T2 t2 ;
public T3 t3 ;
public T4 t4 ;
public T5 t5 ;
public T6 t6 ;
public T7 t7 ;
public T8 t8 ;
public MHA ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 , T6 t6 , T7 t7 , T8 t8 )
{
this . t1 = t1 ;
this . t2 = t2 ;
this . t3 = t3 ;
this . t4 = t4 ;
this . t5 = t5 ;
this . t6 = t6 ;
this . t7 = t7 ;
this . t8 = t8 ;
}
}
public delegate void MHV ( ) ;
public delegate void MHV < T1 > ( T1 t1 ) ;
public delegate void MHV < T1 , T2 > ( T1 t1 , T2 t2 ) ;
public delegate void MHV < T1 , T2 , T3 > ( T1 t1 , T2 t2 , T3 t3 ) ;
public delegate void MHV < T1 , T2 , T3 , T4 > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 ) ;
public delegate void MHV < T1 , T2 , T3 , T4 , T5 > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 ) ;
public delegate void MHV < T1 , T2 , T3 , T4 , T5 , T6 > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 , T6 t6 ) ;
public delegate void MHV < T1 , T2 , T3 , T4 , T5 , T6 , T7 > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 , T6 t6 , T7 t7 ) ;
public delegate void MHV < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 , T6 t6 , T7 t7 , T8 t8 ) ;
public delegate TResult MH < TResult > ( ) ;
public delegate TResult MH < T1 , TResult > ( T1 t1 ) ;
public delegate TResult MH < T1 , T2 , TResult > ( T1 t1 , T2 t2 ) ;
public delegate TResult MH < T1 , T2 , T3 , TResult > ( T1 t1 , T2 t2 , T3 t3 ) ;
public delegate TResult MH < T1 , T2 , T3 , T4 , TResult > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 ) ;
public delegate TResult MH < T1 , T2 , T3 , T4 , T5 , TResult > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 ) ;
public delegate TResult MH < T1 , T2 , T3 , T4 , T5 , T6 , TResult > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 , T6 t6 ) ;
public delegate TResult MH < T1 , T2 , T3 , T4 , T5 , T6 , T7 , TResult > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 , T6 t6 , T7 t7 ) ;
public delegate TResult MH < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , TResult > ( T1 t1 , T2 t2 , T3 t3 , T4 t4 , T5 t5 , T6 t6 , T7 t7 , T8 t8 ) ;
2015-08-26 07:17:56 -04:00
public static class LiveObjectHolder < T >
{
public static object [ ] values ;
}
2014-08-13 10:39:27 +01:00
}