2002-12-18 19:00:25 +03:00
/ *
2008-05-09 09:57:55 +04: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 ;
2008-05-09 09:57:55 +04:00
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
{
2008-08-06 09:25:18 +04: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 ;
}
2009-01-06 12:47:59 +03:00
// 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
}
2008-08-06 09:25:18 +04:00
}
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 )
{
2007-04-23 12:24:33 +04:00
#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
}
2008-08-06 09:25:18 +04:00
[DebuggerStepThroughAttribute]
public static object multianewarray_ghost ( RuntimeTypeHandle typeHandle , int [ ] lengths )
{
Type type = Type . GetTypeFromHandle ( typeHandle ) ;
int rank = 0 ;
2010-02-26 16:31:39 +03:00
while ( ReflectUtil . IsVector ( type ) )
2008-08-06 09:25:18 +04:00
{
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 ;
}
2009-08-28 10:47:16 +04:00
#if ! 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 )
{
2007-04-23 12:24:33 +04:00
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 )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NoSuchFieldError ( clazz + "." + name ) ;
2004-09-09 15:17:55 +04:00
}
// TODO check loader constraints
if ( field . IsStatic ! = isStatic )
{
2007-04-23 12:24:33 +04:00
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 ;
}
2007-04-23 12:24:33 +04:00
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]
2008-08-21 10:09:33 +04:00
public static object DynamicGetfield ( object obj , string name , string sig , RuntimeTypeHandle type , string clazz , ikvm . @internal . CallerID callerID )
2004-09-09 15:17:55 +04:00
{
Profiler . Count ( "DynamicGetfield" ) ;
2008-08-21 10:09:33 +04:00
FieldWrapper fw = GetFieldWrapper ( ClassLoaderWrapper . GetWrapperFromType ( obj . GetType ( ) ) , type , clazz , name , sig , false ) ;
java . lang . reflect . Field field = ( java . lang . reflect . Field ) fw . ToField ( false ) ;
object val = field . get ( obj , callerID ) ;
if ( fw . FieldTypeWrapper . IsPrimitive )
{
val = JVM . Unbox ( val ) ;
}
return val ;
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]
2008-08-21 10:09:33 +04:00
public static object DynamicGetstatic ( string name , string sig , RuntimeTypeHandle type , string clazz , ikvm . @internal . CallerID callerID )
2004-09-09 15:17:55 +04:00
{
Profiler . Count ( "DynamicGetstatic" ) ;
2008-08-21 10:09:33 +04:00
FieldWrapper fw = GetFieldWrapper ( null , type , clazz , name , sig , true ) ;
java . lang . reflect . Field field = ( java . lang . reflect . Field ) fw . ToField ( false ) ;
object val = field . get ( null , callerID ) ;
if ( fw . FieldTypeWrapper . IsPrimitive )
{
val = JVM . Unbox ( val ) ;
}
return val ;
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]
2008-08-21 10:09:33 +04:00
public static void DynamicPutfield ( object obj , object val , string name , string sig , RuntimeTypeHandle type , string clazz , ikvm . @internal . CallerID callerID )
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 )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . IllegalAccessError ( "Field " + fw . DeclaringType . Name + "." + fw . Name + " is final" ) ;
2004-09-09 15:17:55 +04:00
}
2008-08-21 10:09:33 +04:00
java . lang . reflect . Field field = ( java . lang . reflect . Field ) fw . ToField ( false ) ;
if ( fw . FieldTypeWrapper . IsPrimitive )
{
val = JVM . Box ( val ) ;
}
field . set ( obj , val , callerID ) ;
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]
2008-08-21 10:09:33 +04:00
public static void DynamicPutstatic ( object val , string name , string sig , RuntimeTypeHandle type , string clazz , ikvm . @internal . CallerID callerID )
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 )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . IllegalAccessError ( "Field " + fw . DeclaringType . Name + "." + fw . Name + " is final" ) ;
2004-09-09 15:17:55 +04:00
}
2008-08-21 10:09:33 +04:00
java . lang . reflect . Field field = ( java . lang . reflect . Field ) fw . ToField ( false ) ;
if ( fw . FieldTypeWrapper . IsPrimitive )
{
val = JVM . Box ( val ) ;
}
field . set ( null , val , callerID ) ;
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
{
2007-04-23 12:24:33 +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 )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NoClassDefFoundError ( clazz ) ;
2004-09-09 15:17:55 +04:00
}
if ( ! wrapper . IsAccessibleFrom ( context ) )
{
2007-04-23 12:24:33 +04:00
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
{
2007-04-23 12:24:33 +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 ) ;
2007-05-31 11:12:56 +04:00
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 )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NoSuchMethodError ( clazz + "." + name + sig ) ;
2004-09-09 15:17:55 +04:00
}
// TODO check loader constraints
if ( mw . IsStatic ! = isStatic )
{
2007-04-23 12:24:33 +04:00
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 ;
}
2007-04-23 12:24:33 +04:00
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]
2008-08-21 10:09:33 +04:00
public static object DynamicInvokeSpecialNew ( RuntimeTypeHandle type , string clazz , string name , string sig , object [ ] args , ikvm . @internal . CallerID callerID )
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicInvokeSpecialNew" ) ;
2008-08-21 10:09:33 +04:00
MethodWrapper mw = GetMethodWrapper ( null , type , clazz , name , sig , false ) ;
java . lang . reflect . Constructor cons = ( java . lang . reflect . Constructor ) mw . ToMethodOrConstructor ( false ) ;
return cons . newInstance ( BoxArgs ( mw , args ) , callerID ) ;
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]
2008-08-21 10:09:33 +04:00
public static object DynamicInvokestatic ( RuntimeTypeHandle type , string clazz , string name , string sig , object [ ] args , ikvm . @internal . CallerID callerID )
2004-09-09 15:17:55 +04:00
{
Profiler . Count ( "DynamicInvokestatic" ) ;
2008-08-21 10:09:33 +04:00
MethodWrapper mw = GetMethodWrapper ( null , type , clazz , name , sig , true ) ;
java . lang . reflect . Method m = ( java . lang . reflect . Method ) mw . ToMethodOrConstructor ( false ) ;
object val = m . invoke ( null , BoxArgs ( mw , args ) , callerID ) ;
if ( mw . ReturnType . IsPrimitive & & mw . ReturnType ! = PrimitiveTypeWrapper . VOID )
{
val = JVM . Unbox ( val ) ;
}
return val ;
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]
2008-08-21 10:09:33 +04:00
public static object DynamicInvokevirtual ( object obj , RuntimeTypeHandle type , string clazz , string name , string sig , object [ ] args , ikvm . @internal . CallerID callerID )
2003-02-27 19:41:47 +03:00
{
2004-09-09 15:17:55 +04:00
Profiler . Count ( "DynamicInvokevirtual" ) ;
2008-08-21 10:09:33 +04:00
MethodWrapper mw = GetMethodWrapper ( ClassLoaderWrapper . GetWrapperFromType ( obj . GetType ( ) ) , type , clazz , name , sig , false ) ;
java . lang . reflect . Method m = ( java . lang . reflect . Method ) mw . ToMethodOrConstructor ( false ) ;
object val = m . invoke ( obj , BoxArgs ( mw , args ) , callerID ) ;
if ( mw . ReturnType . IsPrimitive & & mw . ReturnType ! = PrimitiveTypeWrapper . VOID )
{
val = JVM . Unbox ( val ) ;
}
return val ;
}
private static object [ ] BoxArgs ( MethodWrapper mw , object [ ] args )
{
TypeWrapper [ ] paramTypes = mw . GetParameters ( ) ;
for ( int i = 0 ; i < paramTypes . Length ; i + + )
{
if ( paramTypes [ i ] . IsPrimitive )
{
args [ i ] = JVM . Box ( args [ i ] ) ;
}
}
return args ;
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 )
{
2009-11-04 08:16:32 +03:00
return null ;
2005-12-19 18:12:49 +03:00
}
[DebuggerStepThroughAttribute]
public static bool DynamicInstanceOf ( object obj , RuntimeTypeHandle type , string clazz )
{
return false ;
}
2009-11-04 08:16:32 +03:00
[DebuggerStepThroughAttribute]
public static Type DynamicGetTypeAsExceptionType ( RuntimeTypeHandle type , string clazz )
{
return null ;
}
2009-08-28 10:47:16 +04:00
#endif //!FIRST_PASS
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
{
2007-04-23 12:24:33 +04: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 )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayStoreException ( ) ;
2005-03-03 11:20:13 +03:00
}
}
else if ( src = = null | | dest = = null )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NullPointerException ( ) ;
2005-03-03 11:20:13 +03:00
}
else if ( len < 0 )
{
2007-04-23 12:24:33 +04:00
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 )
{
// for small copies, don't bother comparing the types as this is relatively expensive
2009-11-05 10:37:46 +03:00
if ( len > 50 & & src . GetType ( ) = = dest . GetType ( ) )
2005-03-03 11:20:13 +03:00
{
arraycopy_fast ( src1 , srcStart , dst1 , destStart , len ) ;
return ;
}
else
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
}
}
2009-11-05 10:37:46 +03:00
else if ( src . GetType ( ) ! = dest . GetType ( ) & &
2005-03-03 11:20:13 +03:00
( IsPrimitiveArrayType ( src . GetType ( ) ) | | IsPrimitiveArrayType ( dest . GetType ( ) ) ) )
{
// we don't want to allow copying a primitive into an object array!
2007-04-23 12:24:33 +04:00
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 )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayStoreException ( ) ;
2005-03-03 11:20:13 +03:00
}
2004-09-09 15:17:55 +04:00
}
}
2007-04-23 12:24:33 +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 )
{
2007-04-23 12:24:33 +04:00
#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 )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NullPointerException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( ArgumentException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
2007-04-23 12:24:33 +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
{
2007-04-23 12:24:33 +04:00
#if ! FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
checked
{
2007-04-02 12:21:14 +04:00
Buffer . BlockCopy ( src , srcStart * 8 , dest , destStart * 8 , len * 8 ) ;
2004-09-09 15:17:55 +04:00
return ;
}
}
catch ( ArgumentNullException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NullPointerException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( OverflowException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( ArgumentException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
2007-04-23 12:24:33 +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
{
2007-04-23 12:24:33 +04:00
#if ! FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
checked
{
2007-04-02 12:21:14 +04:00
Buffer . BlockCopy ( src , srcStart * 4 , dest , destStart * 4 , len * 4 ) ;
2004-09-09 15:17:55 +04:00
return ;
}
}
catch ( ArgumentNullException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NullPointerException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( OverflowException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( ArgumentException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
2007-04-23 12:24:33 +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
{
2007-04-23 12:24:33 +04:00
#if ! FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
checked
{
2007-04-02 12:21:14 +04:00
Buffer . BlockCopy ( src , srcStart * 2 , dest , destStart * 2 , len * 2 ) ;
2004-09-09 15:17:55 +04:00
return ;
}
}
catch ( ArgumentNullException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NullPointerException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( OverflowException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( ArgumentException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
2007-04-23 12:24:33 +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
{
2007-04-23 12:24:33 +04:00
#if ! FIRST_PASS
2004-09-09 15:17:55 +04:00
try
{
Buffer . BlockCopy ( src , srcStart , dest , destStart , len ) ;
return ;
}
catch ( ArgumentNullException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . NullPointerException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( OverflowException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
catch ( ArgumentException )
{
2007-04-23 12:24:33 +04:00
throw new java . lang . ArrayIndexOutOfBoundsException ( ) ;
2004-09-09 15:17:55 +04:00
}
2007-04-23 12:24:33 +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 )
{
2007-04-23 12:24:33 +04:00
#if ! FIRST_PASS
2008-04-21 08:27:59 +04:00
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 ) ;
}
2007-04-23 12:24:33 +04:00
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 ( )
{
2009-08-28 10:47:16 +04:00
#if FIRST_PASS
2005-12-07 12:06:32 +03:00
return false ;
#else
2008-08-06 16:22:06 +04:00
return Environment . HasShutdownStarted & & ! java . lang . Shutdown . runFinalizersOnExit ;
2006-06-08 13:26:33 +04:00
#endif
}
public static long VolatileRead ( ref long v )
{
return Interlocked . Read ( ref v ) ;
}
public static void VolatileWrite ( ref long v , long newValue )
{
Interlocked . Exchange ( ref v , newValue ) ;
}
public static double VolatileRead ( ref double v )
{
return Interlocked . CompareExchange ( ref v , 0.0 , 0.0 ) ;
}
public static void VolatileWrite ( ref double v , double newValue )
{
Interlocked . Exchange ( ref v , newValue ) ;
2005-05-02 14:03:21 +04:00
}
2009-11-03 10:15:37 +03: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 ) ;
}
}
2009-11-09 11:52:17 +03:00
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
}
2003-02-27 19:41:47 +03:00
}
2008-05-09 09:57:55 +04: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
}