2014-08-13 10:39:27 +01:00
/ *
2015-08-26 07:17:56 -04:00
Copyright ( C ) 2007 - 2014 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.Diagnostics ;
using System.Collections.Generic ;
using System.Reflection ;
#if ! NO_REF_EMIT
using System.Reflection.Emit ;
#endif
using System.Runtime.CompilerServices ;
using System.Runtime.Serialization ;
using System.Security ;
using IKVM.Internal ;
2015-08-26 07:17:56 -04:00
using IKVM.Attributes ;
2014-08-13 10:39:27 +01:00
namespace IKVM.Internal
{
#if ! FIRST_PASS
public interface IReflectionException
{
java . lang . IllegalArgumentException GetIllegalArgumentException ( object obj ) ;
java . lang . IllegalArgumentException SetIllegalArgumentException ( object obj ) ;
}
#endif
}
static class Java_sun_reflect_Reflection
{
#if CLASSGC
2015-08-26 07:17:56 -04:00
sealed class State
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
internal HideFromJavaFlags Value ;
internal volatile bool HasValue ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
private static readonly ConditionalWeakTable < MethodBase , State > isHideFromJavaCache = new ConditionalWeakTable < MethodBase , State > ( ) ;
internal static HideFromJavaFlags GetHideFromJavaFlags ( MethodBase mb )
2014-08-13 10:39:27 +01:00
{
if ( mb . Name . StartsWith ( "__<" , StringComparison . Ordinal ) )
{
2015-08-26 07:17:56 -04:00
return HideFromJavaFlags . All ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
State state = isHideFromJavaCache . GetValue ( mb , delegate { return new State ( ) ; } ) ;
if ( ! state . HasValue )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
state . Value = AttributeHelper . GetHideFromJavaFlags ( mb ) ;
state . HasValue = true ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
return state . Value ;
2014-08-13 10:39:27 +01:00
}
#else
2015-08-26 07:17:56 -04:00
private static readonly Dictionary < RuntimeMethodHandle , HideFromJavaFlags > isHideFromJavaCache = new Dictionary < RuntimeMethodHandle , HideFromJavaFlags > ( ) ;
2014-08-13 10:39:27 +01:00
2015-08-26 07:17:56 -04:00
internal static HideFromJavaFlags GetHideFromJavaFlags ( MethodBase mb )
2014-08-13 10:39:27 +01:00
{
if ( mb . Name . StartsWith ( "__<" , StringComparison . Ordinal ) )
{
2015-08-26 07:17:56 -04:00
return HideFromJavaFlags . All ;
2014-08-13 10:39:27 +01:00
}
RuntimeMethodHandle handle ;
try
{
handle = mb . MethodHandle ;
}
catch ( InvalidOperationException )
{
// DynamicMethods don't have a RuntimeMethodHandle and we always want to hide them anyway
2015-08-26 07:17:56 -04:00
return HideFromJavaFlags . All ;
2014-08-13 10:39:27 +01:00
}
catch ( NotSupportedException )
{
// DynamicMethods don't have a RuntimeMethodHandle and we always want to hide them anyway
2015-08-26 07:17:56 -04:00
return HideFromJavaFlags . All ;
2014-08-13 10:39:27 +01:00
}
lock ( isHideFromJavaCache )
{
2015-08-26 07:17:56 -04:00
HideFromJavaFlags cached ;
2014-08-13 10:39:27 +01:00
if ( isHideFromJavaCache . TryGetValue ( handle , out cached ) )
{
return cached ;
}
}
2015-08-26 07:17:56 -04:00
HideFromJavaFlags flags = AttributeHelper . GetHideFromJavaFlags ( mb ) ;
2014-08-13 10:39:27 +01:00
lock ( isHideFromJavaCache )
{
2015-08-26 07:17:56 -04:00
isHideFromJavaCache [ handle ] = flags ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
return flags ;
2014-08-13 10:39:27 +01:00
}
#endif
2015-08-26 07:17:56 -04:00
internal static bool IsHideFromStackWalk ( MethodBase mb )
{
Type type = mb . DeclaringType ;
return type = = null
| | type . Assembly = = typeof ( object ) . Assembly
| | type . Assembly = = typeof ( Java_sun_reflect_Reflection ) . Assembly
| | type . Assembly = = Java_java_lang_SecurityManager . jniAssembly
| | type = = typeof ( java . lang . reflect . Method )
| | type = = typeof ( java . lang . reflect . Constructor )
| | ( GetHideFromJavaFlags ( mb ) & HideFromJavaFlags . StackWalk ) ! = 0
;
}
public static java . lang . Class getCallerClass ( )
{
#if FIRST_PASS
return null ;
#else
throw new java . lang . InternalError ( "CallerSensitive annotation expected at frame 1" ) ;
#endif
}
2014-08-13 10:39:27 +01:00
// NOTE this method is hooked up explicitly through map.xml to prevent inlining of the native stub
// and tail-call optimization in the native stub.
2015-08-26 07:17:56 -04:00
public static java . lang . Class getCallerClass ( int realFramesToSkip )
2014-08-13 10:39:27 +01:00
{
#if FIRST_PASS
return null ;
#else
2015-08-26 07:17:56 -04:00
if ( realFramesToSkip < = 0 )
2014-08-13 10:39:27 +01:00
{
2015-08-26 07:17:56 -04:00
return ikvm . @internal . ClassLiteral < sun . reflect . Reflection > . Value ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
for ( int i = 2 ; ; )
2014-08-13 10:39:27 +01:00
{
MethodBase method = new StackFrame ( i + + , false ) . GetMethod ( ) ;
if ( method = = null )
{
return null ;
}
2015-08-26 07:17:56 -04:00
if ( IsHideFromStackWalk ( method ) )
{
continue ;
}
// HACK we skip HideFromJavaFlags.StackTrace too because we want to skip the LambdaForm methods
// that are used by late binding
if ( ( GetHideFromJavaFlags ( method ) & HideFromJavaFlags . StackTrace ) ! = 0 )
2014-08-13 10:39:27 +01:00
{
continue ;
}
if ( - - realFramesToSkip = = 0 )
{
2015-08-26 07:17:56 -04:00
return ClassLoaderWrapper . GetWrapperFromType ( method . DeclaringType ) . ClassObject ;
2014-08-13 10:39:27 +01:00
}
}
#endif
}
public static int getClassAccessFlags ( java . lang . Class clazz )
{
// the mask comes from JVM_RECOGNIZED_CLASS_MODIFIERS in src/hotspot/share/vm/prims/jvm.h
int mods = ( int ) TypeWrapper . FromClass ( clazz ) . Modifiers & 0x7631 ;
// interface implies abstract
mods | = ( mods & 0x0200 ) < < 1 ;
return mods ;
}
public static bool checkInternalAccess ( java . lang . Class currentClass , java . lang . Class memberClass )
{
TypeWrapper current = TypeWrapper . FromClass ( currentClass ) ;
TypeWrapper member = TypeWrapper . FromClass ( memberClass ) ;
return member . IsInternal & & member . InternalsVisibleTo ( current ) ;
}
}
static class Java_sun_reflect_ReflectionFactory
{
#if ! FIRST_PASS
private static object ConvertPrimitive ( TypeWrapper tw , object value )
{
if ( tw = = PrimitiveTypeWrapper . BOOLEAN )
{
if ( value is java . lang . Boolean )
{
return ( ( java . lang . Boolean ) value ) . booleanValue ( ) ;
}
}
else if ( tw = = PrimitiveTypeWrapper . BYTE )
{
if ( value is java . lang . Byte )
{
return ( ( java . lang . Byte ) value ) . byteValue ( ) ;
}
}
else if ( tw = = PrimitiveTypeWrapper . CHAR )
{
if ( value is java . lang . Character )
{
return ( ( java . lang . Character ) value ) . charValue ( ) ;
}
}
else if ( tw = = PrimitiveTypeWrapper . SHORT )
{
if ( value is java . lang . Short | | value is java . lang . Byte )
{
return ( ( java . lang . Number ) value ) . shortValue ( ) ;
}
}
else if ( tw = = PrimitiveTypeWrapper . INT )
{
if ( value is java . lang . Integer | | value is java . lang . Short | | value is java . lang . Byte )
{
return ( ( java . lang . Number ) value ) . intValue ( ) ;
}
else if ( value is java . lang . Character )
{
return ( int ) ( ( java . lang . Character ) value ) . charValue ( ) ;
}
}
else if ( tw = = PrimitiveTypeWrapper . LONG )
{
if ( value is java . lang . Long | | value is java . lang . Integer | | value is java . lang . Short | | value is java . lang . Byte )
{
return ( ( java . lang . Number ) value ) . longValue ( ) ;
}
else if ( value is java . lang . Character )
{
return ( long ) ( ( java . lang . Character ) value ) . charValue ( ) ;
}
}
else if ( tw = = PrimitiveTypeWrapper . FLOAT )
{
if ( value is java . lang . Float | | value is java . lang . Long | | value is java . lang . Integer | | value is java . lang . Short | | value is java . lang . Byte )
{
return ( ( java . lang . Number ) value ) . floatValue ( ) ;
}
else if ( value is java . lang . Character )
{
return ( float ) ( ( java . lang . Character ) value ) . charValue ( ) ;
}
}
else if ( tw = = PrimitiveTypeWrapper . DOUBLE )
{
if ( value is java . lang . Double | | value is java . lang . Float | | value is java . lang . Long | | value is java . lang . Integer | | value is java . lang . Short | | value is java . lang . Byte )
{
return ( ( java . lang . Number ) value ) . doubleValue ( ) ;
}
else if ( value is java . lang . Character )
{
return ( double ) ( ( java . lang . Character ) value ) . charValue ( ) ;
}
}
throw new java . lang . IllegalArgumentException ( ) ;
}
private static object [ ] ConvertArgs ( ClassLoaderWrapper loader , TypeWrapper [ ] argumentTypes , object [ ] args )
{
object [ ] nargs = new object [ args = = null ? 0 : args . Length ] ;
if ( nargs . Length ! = argumentTypes . Length )
{
throw new java . lang . IllegalArgumentException ( "wrong number of arguments" ) ;
}
for ( int i = 0 ; i < nargs . Length ; i + + )
{
if ( argumentTypes [ i ] . IsPrimitive )
{
nargs [ i ] = ConvertPrimitive ( argumentTypes [ i ] , args [ i ] ) ;
}
else
{
if ( args [ i ] ! = null & & ! argumentTypes [ i ] . EnsureLoadable ( loader ) . IsInstance ( args [ i ] ) )
{
throw new java . lang . IllegalArgumentException ( ) ;
}
nargs [ i ] = argumentTypes [ i ] . GhostWrap ( args [ i ] ) ;
}
}
return nargs ;
}
private sealed class MethodAccessorImpl : sun . reflect . MethodAccessor
{
private readonly MethodWrapper mw ;
internal MethodAccessorImpl ( MethodWrapper mw )
{
this . mw = mw ;
mw . Link ( ) ;
mw . ResolveMethod ( ) ;
}
[IKVM.Attributes.HideFromJava]
public object invoke ( object obj , object [ ] args , ikvm . @internal . CallerID callerID )
{
if ( ! mw . IsStatic & & ! mw . DeclaringType . IsInstance ( obj ) )
{
if ( obj = = null )
{
throw new java . lang . NullPointerException ( ) ;
}
throw new java . lang . IllegalArgumentException ( "object is not an instance of declaring class" ) ;
}
args = ConvertArgs ( mw . DeclaringType . GetClassLoader ( ) , mw . GetParameters ( ) , args ) ;
// if the method is an interface method, we must explicitly run <clinit>,
// because .NET reflection doesn't
if ( mw . DeclaringType . IsInterface )
{
mw . DeclaringType . RunClassInit ( ) ;
}
if ( mw . HasCallerID )
{
args = ArrayUtil . Concat ( args , callerID ) ;
}
object retval ;
try
{
retval = mw . Invoke ( obj , args ) ;
}
catch ( Exception x )
{
throw new java . lang . reflect . InvocationTargetException ( ikvm . runtime . Util . mapException ( x ) ) ;
}
if ( mw . ReturnType . IsPrimitive & & mw . ReturnType ! = PrimitiveTypeWrapper . VOID )
{
retval = JVM . Box ( retval ) ;
}
else
{
retval = mw . ReturnType . GhostUnwrap ( retval ) ;
}
return retval ;
}
}
private sealed class ConstructorAccessorImpl : sun . reflect . ConstructorAccessor
{
private readonly MethodWrapper mw ;
internal ConstructorAccessorImpl ( MethodWrapper mw )
{
this . mw = mw ;
mw . Link ( ) ;
mw . ResolveMethod ( ) ;
}
[IKVM.Attributes.HideFromJava]
public object newInstance ( object [ ] args )
{
args = ConvertArgs ( mw . DeclaringType . GetClassLoader ( ) , mw . GetParameters ( ) , args ) ;
try
{
return mw . CreateInstance ( args ) ;
}
catch ( Exception x )
{
throw new java . lang . reflect . InvocationTargetException ( ikvm . runtime . Util . mapException ( x ) ) ;
}
}
}
private sealed class SerializationConstructorAccessorImpl : sun . reflect . ConstructorAccessor
{
private readonly MethodWrapper mw ;
private readonly Type type ;
internal SerializationConstructorAccessorImpl ( java . lang . reflect . Constructor constructorToCall , java . lang . Class classToInstantiate )
{
this . type = TypeWrapper . FromClass ( classToInstantiate ) . TypeAsBaseType ;
2015-08-26 07:17:56 -04:00
MethodWrapper mw = MethodWrapper . FromExecutable ( constructorToCall ) ;
2014-08-13 10:39:27 +01:00
if ( mw . DeclaringType ! = CoreClasses . java . lang . Object . Wrapper )
{
this . mw = mw ;
mw . Link ( ) ;
mw . ResolveMethod ( ) ;
}
}
[IKVM.Attributes.HideFromJava]
[SecuritySafeCritical]
public object newInstance ( object [ ] args )
{
object obj = FormatterServices . GetUninitializedObject ( type ) ;
if ( mw ! = null )
{
mw . Invoke ( obj , ConvertArgs ( mw . DeclaringType . GetClassLoader ( ) , mw . GetParameters ( ) , args ) ) ;
}
return obj ;
}
}
#if ! NO_REF_EMIT
private sealed class BoxUtil
{
private static readonly MethodInfo valueOfByte = typeof ( java . lang . Byte ) . GetMethod ( "valueOf" , new Type [ ] { typeof ( byte ) } ) ;
private static readonly MethodInfo valueOfBoolean = typeof ( java . lang . Boolean ) . GetMethod ( "valueOf" , new Type [ ] { typeof ( bool ) } ) ;
private static readonly MethodInfo valueOfChar = typeof ( java . lang . Character ) . GetMethod ( "valueOf" , new Type [ ] { typeof ( char ) } ) ;
private static readonly MethodInfo valueOfShort = typeof ( java . lang . Short ) . GetMethod ( "valueOf" , new Type [ ] { typeof ( short ) } ) ;
private static readonly MethodInfo valueOfInt = typeof ( java . lang . Integer ) . GetMethod ( "valueOf" , new Type [ ] { typeof ( int ) } ) ;
private static readonly MethodInfo valueOfFloat = typeof ( java . lang . Float ) . GetMethod ( "valueOf" , new Type [ ] { typeof ( float ) } ) ;
private static readonly MethodInfo valueOfLong = typeof ( java . lang . Long ) . GetMethod ( "valueOf" , new Type [ ] { typeof ( long ) } ) ;
private static readonly MethodInfo valueOfDouble = typeof ( java . lang . Double ) . GetMethod ( "valueOf" , new Type [ ] { typeof ( double ) } ) ;
private static readonly MethodInfo byteValue = typeof ( java . lang . Byte ) . GetMethod ( "byteValue" , Type . EmptyTypes ) ;
private static readonly MethodInfo booleanValue = typeof ( java . lang . Boolean ) . GetMethod ( "booleanValue" , Type . EmptyTypes ) ;
private static readonly MethodInfo charValue = typeof ( java . lang . Character ) . GetMethod ( "charValue" , Type . EmptyTypes ) ;
private static readonly MethodInfo shortValue = typeof ( java . lang . Short ) . GetMethod ( "shortValue" , Type . EmptyTypes ) ;
private static readonly MethodInfo intValue = typeof ( java . lang . Integer ) . GetMethod ( "intValue" , Type . EmptyTypes ) ;
private static readonly MethodInfo floatValue = typeof ( java . lang . Float ) . GetMethod ( "floatValue" , Type . EmptyTypes ) ;
private static readonly MethodInfo longValue = typeof ( java . lang . Long ) . GetMethod ( "longValue" , Type . EmptyTypes ) ;
private static readonly MethodInfo doubleValue = typeof ( java . lang . Double ) . GetMethod ( "doubleValue" , Type . EmptyTypes ) ;
internal static void EmitUnboxArg ( CodeEmitter ilgen , TypeWrapper type )
{
if ( type = = PrimitiveTypeWrapper . BYTE )
{
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Byte ) ) ;
ilgen . Emit ( OpCodes . Call , byteValue ) ;
}
else if ( type = = PrimitiveTypeWrapper . BOOLEAN )
{
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Boolean ) ) ;
ilgen . Emit ( OpCodes . Call , booleanValue ) ;
}
else if ( type = = PrimitiveTypeWrapper . CHAR )
{
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Character ) ) ;
ilgen . Emit ( OpCodes . Call , charValue ) ;
}
else if ( type = = PrimitiveTypeWrapper . SHORT
| | type = = PrimitiveTypeWrapper . INT
| | type = = PrimitiveTypeWrapper . FLOAT
| | type = = PrimitiveTypeWrapper . LONG
| | type = = PrimitiveTypeWrapper . DOUBLE )
{
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Isinst , typeof ( java . lang . Byte ) ) ;
CodeEmitterLabel next = ilgen . DefineLabel ( ) ;
ilgen . EmitBrfalse ( next ) ;
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Byte ) ) ;
ilgen . Emit ( OpCodes . Call , byteValue ) ;
ilgen . Emit ( OpCodes . Conv_I1 ) ;
Expand ( ilgen , type ) ;
CodeEmitterLabel done = ilgen . DefineLabel ( ) ;
ilgen . EmitBr ( done ) ;
ilgen . MarkLabel ( next ) ;
if ( type = = PrimitiveTypeWrapper . SHORT )
{
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Short ) ) ;
ilgen . Emit ( OpCodes . Call , shortValue ) ;
}
else
{
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Isinst , typeof ( java . lang . Short ) ) ;
next = ilgen . DefineLabel ( ) ;
ilgen . EmitBrfalse ( next ) ;
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Short ) ) ;
ilgen . Emit ( OpCodes . Call , shortValue ) ;
Expand ( ilgen , type ) ;
ilgen . EmitBr ( done ) ;
ilgen . MarkLabel ( next ) ;
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Isinst , typeof ( java . lang . Character ) ) ;
next = ilgen . DefineLabel ( ) ;
ilgen . EmitBrfalse ( next ) ;
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Character ) ) ;
ilgen . Emit ( OpCodes . Call , charValue ) ;
Expand ( ilgen , type ) ;
ilgen . EmitBr ( done ) ;
ilgen . MarkLabel ( next ) ;
if ( type = = PrimitiveTypeWrapper . INT )
{
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Integer ) ) ;
ilgen . Emit ( OpCodes . Call , intValue ) ;
}
else
{
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Isinst , typeof ( java . lang . Integer ) ) ;
next = ilgen . DefineLabel ( ) ;
ilgen . EmitBrfalse ( next ) ;
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Integer ) ) ;
ilgen . Emit ( OpCodes . Call , intValue ) ;
Expand ( ilgen , type ) ;
ilgen . EmitBr ( done ) ;
ilgen . MarkLabel ( next ) ;
if ( type = = PrimitiveTypeWrapper . LONG )
{
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Long ) ) ;
ilgen . Emit ( OpCodes . Call , longValue ) ;
}
else
{
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Isinst , typeof ( java . lang . Long ) ) ;
next = ilgen . DefineLabel ( ) ;
ilgen . EmitBrfalse ( next ) ;
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Long ) ) ;
ilgen . Emit ( OpCodes . Call , longValue ) ;
Expand ( ilgen , type ) ;
ilgen . EmitBr ( done ) ;
ilgen . MarkLabel ( next ) ;
if ( type = = PrimitiveTypeWrapper . FLOAT )
{
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Float ) ) ;
ilgen . Emit ( OpCodes . Call , floatValue ) ;
}
else if ( type = = PrimitiveTypeWrapper . DOUBLE )
{
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Isinst , typeof ( java . lang . Float ) ) ;
next = ilgen . DefineLabel ( ) ;
ilgen . EmitBrfalse ( next ) ;
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Float ) ) ;
ilgen . Emit ( OpCodes . Call , floatValue ) ;
ilgen . EmitBr ( done ) ;
ilgen . MarkLabel ( next ) ;
ilgen . Emit ( OpCodes . Castclass , typeof ( java . lang . Double ) ) ;
ilgen . Emit ( OpCodes . Call , doubleValue ) ;
}
else
{
throw new InvalidOperationException ( ) ;
}
}
}
}
ilgen . MarkLabel ( done ) ;
}
else
{
type . EmitCheckcast ( ilgen ) ;
}
}
internal static void BoxReturnValue ( CodeEmitter ilgen , TypeWrapper type )
{
if ( type = = PrimitiveTypeWrapper . VOID )
{
ilgen . Emit ( OpCodes . Ldnull ) ;
}
else if ( type = = PrimitiveTypeWrapper . BYTE )
{
ilgen . Emit ( OpCodes . Call , valueOfByte ) ;
}
else if ( type = = PrimitiveTypeWrapper . BOOLEAN )
{
ilgen . Emit ( OpCodes . Call , valueOfBoolean ) ;
}
else if ( type = = PrimitiveTypeWrapper . CHAR )
{
ilgen . Emit ( OpCodes . Call , valueOfChar ) ;
}
else if ( type = = PrimitiveTypeWrapper . SHORT )
{
ilgen . Emit ( OpCodes . Call , valueOfShort ) ;
}
else if ( type = = PrimitiveTypeWrapper . INT )
{
ilgen . Emit ( OpCodes . Call , valueOfInt ) ;
}
else if ( type = = PrimitiveTypeWrapper . FLOAT )
{
ilgen . Emit ( OpCodes . Call , valueOfFloat ) ;
}
else if ( type = = PrimitiveTypeWrapper . LONG )
{
ilgen . Emit ( OpCodes . Call , valueOfLong ) ;
}
else if ( type = = PrimitiveTypeWrapper . DOUBLE )
{
ilgen . Emit ( OpCodes . Call , valueOfDouble ) ;
}
}
private static void Expand ( CodeEmitter ilgen , TypeWrapper type )
{
if ( type = = PrimitiveTypeWrapper . FLOAT )
{
ilgen . Emit ( OpCodes . Conv_R4 ) ;
}
else if ( type = = PrimitiveTypeWrapper . LONG )
{
ilgen . Emit ( OpCodes . Conv_I8 ) ;
}
else if ( type = = PrimitiveTypeWrapper . DOUBLE )
{
ilgen . Emit ( OpCodes . Conv_R8 ) ;
}
}
}
private sealed class FastMethodAccessorImpl : sun . reflect . MethodAccessor
{
internal static readonly ConstructorInfo invocationTargetExceptionCtor ;
internal static readonly ConstructorInfo illegalArgumentExceptionCtor ;
internal static readonly MethodInfo get_TargetSite ;
internal static readonly MethodInfo GetCurrentMethod ;
private delegate object Invoker ( object obj , object [ ] args , ikvm . @internal . CallerID callerID ) ;
private Invoker invoker ;
static FastMethodAccessorImpl ( )
{
invocationTargetExceptionCtor = typeof ( java . lang . reflect . InvocationTargetException ) . GetConstructor ( new Type [ ] { typeof ( Exception ) } ) ;
illegalArgumentExceptionCtor = typeof ( java . lang . IllegalArgumentException ) . GetConstructor ( Type . EmptyTypes ) ;
get_TargetSite = typeof ( Exception ) . GetMethod ( "get_TargetSite" ) ;
GetCurrentMethod = typeof ( MethodBase ) . GetMethod ( "GetCurrentMethod" ) ;
}
private sealed class RunClassInit
{
private FastMethodAccessorImpl outer ;
private TypeWrapper tw ;
private Invoker invoker ;
internal RunClassInit ( FastMethodAccessorImpl outer , TypeWrapper tw , Invoker invoker )
{
this . outer = outer ;
this . tw = tw ;
this . invoker = invoker ;
}
[IKVM.Attributes.HideFromJava]
internal object invoke ( object obj , object [ ] args , ikvm . @internal . CallerID callerID )
{
// FXBUG pre-SP1 a DynamicMethod that calls a static method doesn't trigger the cctor, so we do that explicitly.
// even on .NET 2.0 SP2, interface method invocations don't run the interface cctor
// NOTE when testing, please test both the x86 and x64 CLR JIT, because they have different bugs (even on .NET 2.0 SP2)
tw . RunClassInit ( ) ;
outer . invoker = invoker ;
return invoker ( obj , args , callerID ) ;
}
}
internal FastMethodAccessorImpl ( MethodWrapper mw )
{
TypeWrapper [ ] parameters ;
try
{
mw . DeclaringType . Finish ( ) ;
parameters = mw . GetParameters ( ) ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
// the EnsureLoadable shouldn't fail, because we don't allow a java.lang.reflect.Method
// to "escape" if it has an unloadable type in the signature
parameters [ i ] = parameters [ i ] . EnsureLoadable ( mw . DeclaringType . GetClassLoader ( ) ) ;
parameters [ i ] . Finish ( ) ;
}
}
catch ( RetargetableJavaException x )
{
throw x . ToJava ( ) ;
}
mw . ResolveMethod ( ) ;
DynamicMethod dm = DynamicMethodUtils . Create ( "__<Invoker>" , mw . DeclaringType . TypeAsBaseType , ! mw . IsPublic | | ! mw . DeclaringType . IsPublic , typeof ( object ) , new Type [ ] { typeof ( object ) , typeof ( object [ ] ) , typeof ( ikvm . @internal . CallerID ) } ) ;
CodeEmitter ilgen = CodeEmitter . Create ( dm ) ;
CodeEmitterLocal ret = ilgen . DeclareLocal ( typeof ( object ) ) ;
if ( ! mw . IsStatic )
{
// check target for null
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . EmitNullCheck ( ) ;
}
// check args length
CodeEmitterLabel argsLengthOK = ilgen . DefineLabel ( ) ;
if ( parameters . Length = = 0 )
{
// zero length array may be null
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . EmitBrfalse ( argsLengthOK ) ;
}
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . Emit ( OpCodes . Ldlen ) ;
ilgen . EmitLdc_I4 ( parameters . Length ) ;
ilgen . EmitBeq ( argsLengthOK ) ;
ilgen . Emit ( OpCodes . Newobj , illegalArgumentExceptionCtor ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . MarkLabel ( argsLengthOK ) ;
int thisCount = mw . IsStatic ? 0 : 1 ;
CodeEmitterLocal [ ] args = new CodeEmitterLocal [ parameters . Length + thisCount ] ;
if ( ! mw . IsStatic )
{
args [ 0 ] = ilgen . DeclareLocal ( mw . DeclaringType . TypeAsSignatureType ) ;
}
for ( int i = thisCount ; i < args . Length ; i + + )
{
args [ i ] = ilgen . DeclareLocal ( parameters [ i - thisCount ] . TypeAsSignatureType ) ;
}
ilgen . BeginExceptionBlock ( ) ;
if ( ! mw . IsStatic )
{
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
mw . DeclaringType . EmitCheckcast ( ilgen ) ;
mw . DeclaringType . EmitConvStackTypeToSignatureType ( ilgen , null ) ;
ilgen . Emit ( OpCodes . Stloc , args [ 0 ] ) ;
}
for ( int i = thisCount ; i < args . Length ; i + + )
{
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . EmitLdc_I4 ( i - thisCount ) ;
ilgen . Emit ( OpCodes . Ldelem_Ref ) ;
TypeWrapper tw = parameters [ i - thisCount ] ;
BoxUtil . EmitUnboxArg ( ilgen , tw ) ;
tw . EmitConvStackTypeToSignatureType ( ilgen , null ) ;
ilgen . Emit ( OpCodes . Stloc , args [ i ] ) ;
}
CodeEmitterLabel label1 = ilgen . DefineLabel ( ) ;
ilgen . EmitLeave ( label1 ) ;
ilgen . BeginCatchBlock ( typeof ( InvalidCastException ) ) ;
ilgen . Emit ( OpCodes . Newobj , illegalArgumentExceptionCtor ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . BeginCatchBlock ( typeof ( NullReferenceException ) ) ;
ilgen . Emit ( OpCodes . Newobj , illegalArgumentExceptionCtor ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . EndExceptionBlock ( ) ;
// this is the actual call
ilgen . MarkLabel ( label1 ) ;
ilgen . BeginExceptionBlock ( ) ;
for ( int i = 0 ; i < args . Length ; i + + )
{
if ( i = = 0 & & ! mw . IsStatic & & ( mw . DeclaringType . IsNonPrimitiveValueType | | mw . DeclaringType . IsGhost ) )
{
ilgen . Emit ( OpCodes . Ldloca , args [ i ] ) ;
}
else
{
ilgen . Emit ( OpCodes . Ldloc , args [ i ] ) ;
}
}
if ( mw . HasCallerID )
{
ilgen . Emit ( OpCodes . Ldarg_2 ) ;
}
if ( mw . IsStatic )
{
mw . EmitCall ( ilgen ) ;
}
else
{
mw . EmitCallvirtReflect ( ilgen ) ;
}
mw . ReturnType . EmitConvSignatureTypeToStackType ( ilgen ) ;
BoxUtil . BoxReturnValue ( ilgen , mw . ReturnType ) ;
ilgen . Emit ( OpCodes . Stloc , ret ) ;
CodeEmitterLabel label2 = ilgen . DefineLabel ( ) ;
ilgen . EmitLeave ( label2 ) ;
ilgen . BeginCatchBlock ( typeof ( Exception ) ) ;
CodeEmitterLabel label = ilgen . DefineLabel ( ) ;
CodeEmitterLabel labelWrap = ilgen . DefineLabel ( ) ;
// If the exception we caught is a java.lang.reflect.InvocationTargetException, we know it must be
// wrapped, because .NET won't throw that exception and we also cannot check the target site,
// because it may be the same as us if a method is recursively invoking itself.
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Isinst , typeof ( java . lang . reflect . InvocationTargetException ) ) ;
ilgen . EmitBrtrue ( labelWrap ) ;
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Callvirt , get_TargetSite ) ;
ilgen . Emit ( OpCodes . Call , GetCurrentMethod ) ;
ilgen . Emit ( OpCodes . Ceq ) ;
ilgen . EmitBrtrue ( label ) ;
ilgen . MarkLabel ( labelWrap ) ;
ilgen . Emit ( OpCodes . Ldc_I4_0 ) ;
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . mapException . MakeGenericMethod ( Types . Exception ) ) ;
ilgen . Emit ( OpCodes . Newobj , invocationTargetExceptionCtor ) ;
ilgen . MarkLabel ( label ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . EndExceptionBlock ( ) ;
ilgen . MarkLabel ( label2 ) ;
ilgen . Emit ( OpCodes . Ldloc , ret ) ;
ilgen . Emit ( OpCodes . Ret ) ;
ilgen . DoEmit ( ) ;
invoker = ( Invoker ) dm . CreateDelegate ( typeof ( Invoker ) ) ;
if ( ( mw . IsStatic | | mw . DeclaringType . IsInterface ) & & mw . DeclaringType . HasStaticInitializer )
{
invoker = new Invoker ( new RunClassInit ( this , mw . DeclaringType , invoker ) . invoke ) ;
}
}
[IKVM.Attributes.HideFromJava]
public object invoke ( object obj , object [ ] args , ikvm . @internal . CallerID callerID )
{
try
{
return invoker ( obj , args , callerID ) ;
}
catch ( MethodAccessException x )
{
// this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
}
private sealed class FastConstructorAccessorImpl : sun . reflect . ConstructorAccessor
{
private delegate object Invoker ( object [ ] args ) ;
private Invoker invoker ;
internal FastConstructorAccessorImpl ( java . lang . reflect . Constructor constructor )
{
2015-08-26 07:17:56 -04:00
MethodWrapper mw = MethodWrapper . FromExecutable ( constructor ) ;
2014-08-13 10:39:27 +01:00
TypeWrapper [ ] parameters ;
try
{
mw . DeclaringType . Finish ( ) ;
parameters = mw . GetParameters ( ) ;
for ( int i = 0 ; i < parameters . Length ; i + + )
{
// the EnsureLoadable shouldn't fail, because we don't allow a java.lang.reflect.Method
// to "escape" if it has an unloadable type in the signature
parameters [ i ] = parameters [ i ] . EnsureLoadable ( mw . DeclaringType . GetClassLoader ( ) ) ;
parameters [ i ] . Finish ( ) ;
}
}
catch ( RetargetableJavaException x )
{
throw x . ToJava ( ) ;
}
mw . ResolveMethod ( ) ;
DynamicMethod dm = DynamicMethodUtils . Create ( "__<Invoker>" , mw . DeclaringType . TypeAsTBD , ! mw . IsPublic | | ! mw . DeclaringType . IsPublic , typeof ( object ) , new Type [ ] { typeof ( object [ ] ) } ) ;
CodeEmitter ilgen = CodeEmitter . Create ( dm ) ;
CodeEmitterLocal ret = ilgen . DeclareLocal ( typeof ( object ) ) ;
// check args length
CodeEmitterLabel argsLengthOK = ilgen . DefineLabel ( ) ;
if ( parameters . Length = = 0 )
{
// zero length array may be null
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . EmitBrfalse ( argsLengthOK ) ;
}
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldlen ) ;
ilgen . EmitLdc_I4 ( parameters . Length ) ;
ilgen . EmitBeq ( argsLengthOK ) ;
ilgen . Emit ( OpCodes . Newobj , FastMethodAccessorImpl . illegalArgumentExceptionCtor ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . MarkLabel ( argsLengthOK ) ;
CodeEmitterLocal [ ] args = new CodeEmitterLocal [ parameters . Length ] ;
for ( int i = 0 ; i < args . Length ; i + + )
{
args [ i ] = ilgen . DeclareLocal ( parameters [ i ] . TypeAsSignatureType ) ;
}
ilgen . BeginExceptionBlock ( ) ;
for ( int i = 0 ; i < args . Length ; i + + )
{
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . EmitLdc_I4 ( i ) ;
ilgen . Emit ( OpCodes . Ldelem_Ref ) ;
TypeWrapper tw = parameters [ i ] ;
BoxUtil . EmitUnboxArg ( ilgen , tw ) ;
tw . EmitConvStackTypeToSignatureType ( ilgen , null ) ;
ilgen . Emit ( OpCodes . Stloc , args [ i ] ) ;
}
CodeEmitterLabel label1 = ilgen . DefineLabel ( ) ;
ilgen . EmitLeave ( label1 ) ;
ilgen . BeginCatchBlock ( typeof ( InvalidCastException ) ) ;
ilgen . Emit ( OpCodes . Newobj , FastMethodAccessorImpl . illegalArgumentExceptionCtor ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . BeginCatchBlock ( typeof ( NullReferenceException ) ) ;
ilgen . Emit ( OpCodes . Newobj , FastMethodAccessorImpl . illegalArgumentExceptionCtor ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . EndExceptionBlock ( ) ;
// this is the actual call
ilgen . MarkLabel ( label1 ) ;
ilgen . BeginExceptionBlock ( ) ;
for ( int i = 0 ; i < args . Length ; i + + )
{
ilgen . Emit ( OpCodes . Ldloc , args [ i ] ) ;
}
mw . EmitNewobj ( ilgen ) ;
ilgen . Emit ( OpCodes . Stloc , ret ) ;
CodeEmitterLabel label2 = ilgen . DefineLabel ( ) ;
ilgen . EmitLeave ( label2 ) ;
ilgen . BeginCatchBlock ( typeof ( Exception ) ) ;
ilgen . Emit ( OpCodes . Dup ) ;
ilgen . Emit ( OpCodes . Callvirt , FastMethodAccessorImpl . get_TargetSite ) ;
ilgen . Emit ( OpCodes . Call , FastMethodAccessorImpl . GetCurrentMethod ) ;
ilgen . Emit ( OpCodes . Ceq ) ;
CodeEmitterLabel label = ilgen . DefineLabel ( ) ;
ilgen . EmitBrtrue ( label ) ;
ilgen . Emit ( OpCodes . Ldc_I4_0 ) ;
ilgen . Emit ( OpCodes . Call , ByteCodeHelperMethods . mapException . MakeGenericMethod ( Types . Exception ) ) ;
ilgen . Emit ( OpCodes . Newobj , FastMethodAccessorImpl . invocationTargetExceptionCtor ) ;
ilgen . MarkLabel ( label ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . EndExceptionBlock ( ) ;
ilgen . MarkLabel ( label2 ) ;
ilgen . Emit ( OpCodes . Ldloc , ret ) ;
ilgen . Emit ( OpCodes . Ret ) ;
ilgen . DoEmit ( ) ;
invoker = ( Invoker ) dm . CreateDelegate ( typeof ( Invoker ) ) ;
}
[IKVM.Attributes.HideFromJava]
public object newInstance ( object [ ] args )
{
try
{
return invoker ( args ) ;
}
catch ( MethodAccessException x )
{
// this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
}
private sealed class FastSerializationConstructorAccessorImpl : sun . reflect . ConstructorAccessor
{
private static readonly MethodInfo GetTypeFromHandleMethod = typeof ( Type ) . GetMethod ( "GetTypeFromHandle" , new Type [ ] { typeof ( RuntimeTypeHandle ) } ) ;
private static readonly MethodInfo GetUninitializedObjectMethod = typeof ( FormatterServices ) . GetMethod ( "GetUninitializedObject" , new Type [ ] { typeof ( Type ) } ) ;
private delegate object InvokeCtor ( ) ;
private InvokeCtor invoker ;
internal FastSerializationConstructorAccessorImpl ( java . lang . reflect . Constructor constructorToCall , java . lang . Class classToInstantiate )
{
2015-08-26 07:17:56 -04:00
MethodWrapper constructor = MethodWrapper . FromExecutable ( constructorToCall ) ;
2014-08-13 10:39:27 +01:00
if ( constructor . GetParameters ( ) . Length ! = 0 )
{
throw new NotImplementedException ( "Serialization constructor cannot have parameters" ) ;
}
constructor . Link ( ) ;
constructor . ResolveMethod ( ) ;
Type type ;
try
{
TypeWrapper wrapper = TypeWrapper . FromClass ( classToInstantiate ) ;
wrapper . Finish ( ) ;
type = wrapper . TypeAsBaseType ;
}
catch ( RetargetableJavaException x )
{
throw x . ToJava ( ) ;
}
DynamicMethod dm = DynamicMethodUtils . Create ( "__<SerializationCtor>" , constructor . DeclaringType . TypeAsBaseType , true , typeof ( object ) , null ) ;
CodeEmitter ilgen = CodeEmitter . Create ( dm ) ;
ilgen . Emit ( OpCodes . Ldtoken , type ) ;
ilgen . Emit ( OpCodes . Call , GetTypeFromHandleMethod ) ;
ilgen . Emit ( OpCodes . Call , GetUninitializedObjectMethod ) ;
ilgen . Emit ( OpCodes . Dup ) ;
constructor . EmitCall ( ilgen ) ;
ilgen . Emit ( OpCodes . Ret ) ;
ilgen . DoEmit ( ) ;
invoker = ( InvokeCtor ) dm . CreateDelegate ( typeof ( InvokeCtor ) ) ;
}
[IKVM.Attributes.HideFromJava]
public object newInstance ( object [ ] args )
{
try
{
return invoker ( ) ;
}
catch ( MethodAccessException x )
{
// this can happen if we're calling a non-public method and the call stack doesn't have ReflectionPermission.MemberAccess
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
}
#endif // !NO_REF_EMIT
sealed class ActivatorConstructorAccessor : sun . reflect . ConstructorAccessor
{
private readonly Type type ;
internal ActivatorConstructorAccessor ( MethodWrapper mw )
{
this . type = mw . DeclaringType . TypeAsBaseType ;
}
public object newInstance ( object [ ] objarr )
{
if ( objarr ! = null & & objarr . Length ! = 0 )
{
throw new java . lang . IllegalArgumentException ( ) ;
}
try
{
return Activator . CreateInstance ( type ) ;
}
catch ( TargetInvocationException x )
{
throw new java . lang . reflect . InvocationTargetException ( ikvm . runtime . Util . mapException ( x . InnerException ) ) ;
}
}
internal static bool IsSuitable ( MethodWrapper mw )
{
MethodBase mb = mw . GetMethod ( ) ;
return mb ! = null
& & mb . IsConstructor
& & mb . IsPublic
& & mb . DeclaringType . IsPublic
& & mb . DeclaringType = = mw . DeclaringType . TypeAsBaseType
& & mb . GetParameters ( ) . Length = = 0 ;
}
}
private abstract class FieldAccessorImplBase : sun . reflect . FieldAccessor , IReflectionException
{
protected static readonly ushort inflationThreshold = 15 ;
protected readonly FieldWrapper fw ;
protected readonly bool isFinal ;
protected ushort numInvocations ;
static FieldAccessorImplBase ( )
{
string str = java . lang . Props . props . getProperty ( "ikvm.reflect.field.inflationThreshold" ) ;
int value ;
if ( str ! = null & & int . TryParse ( str , out value ) )
{
if ( value > = ushort . MinValue & & value < = ushort . MaxValue )
{
inflationThreshold = ( ushort ) value ;
}
}
}
2015-08-26 07:17:56 -04:00
private FieldAccessorImplBase ( FieldWrapper fw , bool isFinal )
2014-08-13 10:39:27 +01:00
{
this . fw = fw ;
2015-08-26 07:17:56 -04:00
this . isFinal = isFinal ;
2014-08-13 10:39:27 +01:00
}
private string GetQualifiedFieldName ( )
{
return fw . DeclaringType . Name + "." + fw . Name ;
}
private string GetFieldTypeName ( )
{
2015-08-26 07:17:56 -04:00
return fw . FieldTypeWrapper . IsPrimitive
? fw . FieldTypeWrapper . ClassObject . getName ( )
: fw . FieldTypeWrapper . Name ;
2014-08-13 10:39:27 +01:00
}
public java . lang . IllegalArgumentException GetIllegalArgumentException ( object obj )
{
// LAME like JDK 6 we return the wrong exception message (talking about setting the field, instead of getting)
return SetIllegalArgumentException ( obj ) ;
}
public java . lang . IllegalArgumentException SetIllegalArgumentException ( object obj )
{
// LAME like JDK 6 we return the wrong exception message (when obj is the object, instead of the value)
return SetIllegalArgumentException ( obj ! = null ? ikvm . runtime . Util . getClassFromObject ( obj ) . getName ( ) : "" , "" ) ;
}
private java . lang . IllegalArgumentException SetIllegalArgumentException ( string attemptedType , string attemptedValue )
{
return new java . lang . IllegalArgumentException ( GetSetMessage ( attemptedType , attemptedValue ) ) ;
}
protected java . lang . IllegalAccessException FinalFieldIllegalAccessException ( object obj )
{
return FinalFieldIllegalAccessException ( obj ! = null ? ikvm . runtime . Util . getClassFromObject ( obj ) . getName ( ) : "" , "" ) ;
}
private java . lang . IllegalAccessException FinalFieldIllegalAccessException ( string attemptedType , string attemptedValue )
{
return new java . lang . IllegalAccessException ( GetSetMessage ( attemptedType , attemptedValue ) ) ;
}
private java . lang . IllegalArgumentException GetIllegalArgumentException ( string type )
{
return new java . lang . IllegalArgumentException ( "Attempt to get " + GetFieldTypeName ( ) + " field \"" + GetQualifiedFieldName ( ) + "\" with illegal data type conversion to " + type ) ;
}
// this message comes from sun.reflect.UnsafeFieldAccessorImpl
private string GetSetMessage ( String attemptedType , String attemptedValue )
{
String err = "Can not set" ;
if ( fw . IsStatic )
err + = " static" ;
if ( isFinal )
err + = " final" ;
err + = " " + GetFieldTypeName ( ) + " field " + GetQualifiedFieldName ( ) + " to " ;
if ( attemptedValue . Length > 0 )
{
err + = "(" + attemptedType + ")" + attemptedValue ;
}
else
{
if ( attemptedType . Length > 0 )
err + = attemptedType ;
else
err + = "null value" ;
}
return err ;
}
public virtual bool getBoolean ( object obj )
{
throw GetIllegalArgumentException ( "boolean" ) ;
}
public virtual byte getByte ( object obj )
{
throw GetIllegalArgumentException ( "byte" ) ;
}
public virtual char getChar ( object obj )
{
throw GetIllegalArgumentException ( "char" ) ;
}
public virtual short getShort ( object obj )
{
throw GetIllegalArgumentException ( "short" ) ;
}
public virtual int getInt ( object obj )
{
throw GetIllegalArgumentException ( "int" ) ;
}
public virtual long getLong ( object obj )
{
throw GetIllegalArgumentException ( "long" ) ;
}
public virtual float getFloat ( object obj )
{
throw GetIllegalArgumentException ( "float" ) ;
}
public virtual double getDouble ( object obj )
{
throw GetIllegalArgumentException ( "double" ) ;
}
public virtual void setBoolean ( object obj , bool z )
{
throw SetIllegalArgumentException ( "boolean" , java . lang . Boolean . toString ( z ) ) ;
}
public virtual void setByte ( object obj , byte b )
{
throw SetIllegalArgumentException ( "byte" , java . lang . Byte . toString ( b ) ) ;
}
public virtual void setChar ( object obj , char c )
{
throw SetIllegalArgumentException ( "char" , java . lang . Character . toString ( c ) ) ;
}
public virtual void setShort ( object obj , short s )
{
throw SetIllegalArgumentException ( "short" , java . lang . Short . toString ( s ) ) ;
}
public virtual void setInt ( object obj , int i )
{
throw SetIllegalArgumentException ( "int" , java . lang . Integer . toString ( i ) ) ;
}
public virtual void setLong ( object obj , long l )
{
throw SetIllegalArgumentException ( "long" , java . lang . Long . toString ( l ) ) ;
}
public virtual void setFloat ( object obj , float f )
{
throw SetIllegalArgumentException ( "float" , java . lang . Float . toString ( f ) ) ;
}
public virtual void setDouble ( object obj , double d )
{
throw SetIllegalArgumentException ( "double" , java . lang . Double . toString ( d ) ) ;
}
public abstract object get ( object obj ) ;
public abstract void set ( object obj , object value ) ;
private abstract class FieldAccessor < T > : FieldAccessorImplBase
{
protected delegate void Setter ( object obj , T value , FieldAccessor < T > acc ) ;
protected delegate T Getter ( object obj , FieldAccessor < T > acc ) ;
private static readonly Setter initialSetter = lazySet ;
private static readonly Getter initialGetter = lazyGet ;
protected Setter setter = initialSetter ;
protected Getter getter = initialGetter ;
2015-08-26 07:17:56 -04:00
internal FieldAccessor ( FieldWrapper fw , bool isFinal )
: base ( fw , isFinal )
2014-08-13 10:39:27 +01:00
{
if ( ! IsSlowPathCompatible ( fw ) )
{
// prevent slow path
numInvocations = inflationThreshold ;
}
}
private bool IsSlowPathCompatible ( FieldWrapper fw )
{
#if ! NO_REF_EMIT
if ( fw . IsVolatile & & ( fw . FieldTypeWrapper = = PrimitiveTypeWrapper . LONG | | fw . FieldTypeWrapper = = PrimitiveTypeWrapper . DOUBLE ) )
{
return false ;
}
#endif
fw . Link ( ) ;
return true ;
}
private static T lazyGet ( object obj , FieldAccessor < T > acc )
{
return acc . lazyGet ( obj ) ;
}
private static void lazySet ( object obj , T value , FieldAccessor < T > acc )
{
acc . lazySet ( obj , value ) ;
}
private T lazyGet ( object obj )
{
#if ! NO_REF_EMIT
if ( numInvocations > = inflationThreshold )
{
// FXBUG it appears that a ldsfld/stsfld in a DynamicMethod doesn't trigger the class constructor
// and if we didn't use the slow path, we haven't yet initialized the class
fw . DeclaringType . RunClassInit ( ) ;
getter = ( Getter ) GenerateFastGetter ( typeof ( Getter ) , typeof ( T ) , fw ) ;
return getter ( obj , this ) ;
}
#endif // !NO_REF_EMIT
if ( fw . IsStatic )
{
obj = null ;
}
else if ( obj = = null )
{
throw new java . lang . NullPointerException ( ) ;
}
else if ( ! fw . DeclaringType . IsInstance ( obj ) )
{
throw GetIllegalArgumentException ( obj ) ;
}
else if ( fw . DeclaringType . IsRemapped & & ! fw . DeclaringType . TypeAsBaseType . IsInstanceOfType ( obj ) )
{
throw GetUnsupportedRemappedFieldException ( obj ) ;
}
if ( numInvocations = = 0 )
{
fw . DeclaringType . RunClassInit ( ) ;
fw . DeclaringType . Finish ( ) ;
fw . ResolveField ( ) ;
}
numInvocations + + ;
return ( T ) fw . FieldTypeWrapper . GhostUnwrap ( fw . GetValue ( obj ) ) ;
}
private void lazySet ( object obj , T value )
{
if ( isFinal )
{
// for some reason Java runs class initialization before checking if the field is final
fw . DeclaringType . RunClassInit ( ) ;
throw FinalFieldIllegalAccessException ( JavaBox ( value ) ) ;
}
#if ! NO_REF_EMIT
if ( numInvocations > = inflationThreshold )
{
// FXBUG it appears that a ldsfld/stsfld in a DynamicMethod doesn't trigger the class constructor
// and if we didn't use the slow path, we haven't yet initialized the class
fw . DeclaringType . RunClassInit ( ) ;
setter = ( Setter ) GenerateFastSetter ( typeof ( Setter ) , typeof ( T ) , fw ) ;
setter ( obj , value , this ) ;
return ;
}
#endif // !NO_REF_EMIT
if ( fw . IsStatic )
{
obj = null ;
}
else if ( obj = = null )
{
throw new java . lang . NullPointerException ( ) ;
}
else if ( ! fw . DeclaringType . IsInstance ( obj ) )
{
throw SetIllegalArgumentException ( obj ) ;
}
else if ( fw . DeclaringType . IsRemapped & & ! fw . DeclaringType . TypeAsBaseType . IsInstanceOfType ( obj ) )
{
throw GetUnsupportedRemappedFieldException ( obj ) ;
}
CheckValue ( value ) ;
if ( numInvocations = = 0 )
{
fw . DeclaringType . RunClassInit ( ) ;
fw . DeclaringType . Finish ( ) ;
fw . ResolveField ( ) ;
}
numInvocations + + ;
fw . SetValue ( obj , fw . FieldTypeWrapper . GhostWrap ( value ) ) ;
}
private Exception GetUnsupportedRemappedFieldException ( object obj )
{
return new java . lang . IllegalAccessException ( "Accessing field " + fw . DeclaringType . Name + "." + fw . Name + " in an object of type " + ikvm . runtime . Util . getClassFromObject ( obj ) . getName ( ) + " is not supported" ) ;
}
protected virtual void CheckValue ( T value )
{
}
protected abstract object JavaBox ( T value ) ;
}
private sealed class ByteField : FieldAccessor < byte >
{
2015-08-26 07:17:56 -04:00
internal ByteField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
public sealed override short getShort ( object obj )
{
return ( sbyte ) getByte ( obj ) ;
}
public sealed override int getInt ( object obj )
{
return ( sbyte ) getByte ( obj ) ;
}
public sealed override long getLong ( object obj )
{
return ( sbyte ) getByte ( obj ) ;
}
public sealed override float getFloat ( object obj )
{
return ( sbyte ) getByte ( obj ) ;
}
public sealed override double getDouble ( object obj )
{
return ( sbyte ) getByte ( obj ) ;
}
public sealed override object get ( object obj )
{
return java . lang . Byte . valueOf ( getByte ( obj ) ) ;
}
public sealed override void set ( object obj , object val )
{
if ( ! ( val is java . lang . Byte ) )
{
throw SetIllegalArgumentException ( val ) ;
}
setByte ( obj , ( ( java . lang . Byte ) val ) . byteValue ( ) ) ;
}
public sealed override byte getByte ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void setByte ( object obj , byte value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( byte value )
{
return java . lang . Byte . valueOf ( value ) ;
}
}
private sealed class BooleanField : FieldAccessor < bool >
{
2015-08-26 07:17:56 -04:00
internal BooleanField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
public sealed override object get ( object obj )
{
return java . lang . Boolean . valueOf ( getBoolean ( obj ) ) ;
}
public sealed override void set ( object obj , object val )
{
if ( ! ( val is java . lang . Boolean ) )
{
throw SetIllegalArgumentException ( val ) ;
}
setBoolean ( obj , ( ( java . lang . Boolean ) val ) . booleanValue ( ) ) ;
}
public sealed override bool getBoolean ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void setBoolean ( object obj , bool value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( bool value )
{
return java . lang . Boolean . valueOf ( value ) ;
}
}
private sealed class CharField : FieldAccessor < char >
{
2015-08-26 07:17:56 -04:00
internal CharField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
public sealed override int getInt ( object obj )
{
return getChar ( obj ) ;
}
public sealed override long getLong ( object obj )
{
return getChar ( obj ) ;
}
public sealed override float getFloat ( object obj )
{
return getChar ( obj ) ;
}
public sealed override double getDouble ( object obj )
{
return getChar ( obj ) ;
}
public sealed override object get ( object obj )
{
return java . lang . Character . valueOf ( getChar ( obj ) ) ;
}
public sealed override void set ( object obj , object val )
{
if ( val is java . lang . Character )
setChar ( obj , ( ( java . lang . Character ) val ) . charValue ( ) ) ;
else
throw SetIllegalArgumentException ( val ) ;
}
public sealed override char getChar ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void setChar ( object obj , char value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( char value )
{
return java . lang . Character . valueOf ( value ) ;
}
}
private sealed class ShortField : FieldAccessor < short >
{
2015-08-26 07:17:56 -04:00
internal ShortField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
public sealed override int getInt ( object obj )
{
return getShort ( obj ) ;
}
public sealed override long getLong ( object obj )
{
return getShort ( obj ) ;
}
public sealed override float getFloat ( object obj )
{
return getShort ( obj ) ;
}
public sealed override double getDouble ( object obj )
{
return getShort ( obj ) ;
}
public sealed override object get ( object obj )
{
return java . lang . Short . valueOf ( getShort ( obj ) ) ;
}
public sealed override void set ( object obj , object val )
{
if ( val is java . lang . Byte
| | val is java . lang . Short )
setShort ( obj , ( ( java . lang . Number ) val ) . shortValue ( ) ) ;
else
throw SetIllegalArgumentException ( val ) ;
}
public sealed override void setByte ( object obj , byte b )
{
setShort ( obj , ( sbyte ) b ) ;
}
public sealed override short getShort ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void setShort ( object obj , short value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( short value )
{
return java . lang . Short . valueOf ( value ) ;
}
}
private sealed class IntField : FieldAccessor < int >
{
2015-08-26 07:17:56 -04:00
internal IntField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
public sealed override long getLong ( object obj )
{
return getInt ( obj ) ;
}
public sealed override float getFloat ( object obj )
{
return getInt ( obj ) ;
}
public sealed override double getDouble ( object obj )
{
return getInt ( obj ) ;
}
public sealed override object get ( object obj )
{
return java . lang . Integer . valueOf ( getInt ( obj ) ) ;
}
public sealed override void set ( object obj , object val )
{
if ( val is java . lang . Byte
| | val is java . lang . Short
| | val is java . lang . Integer )
setInt ( obj , ( ( java . lang . Number ) val ) . intValue ( ) ) ;
else if ( val is java . lang . Character )
setInt ( obj , ( ( java . lang . Character ) val ) . charValue ( ) ) ;
else
throw SetIllegalArgumentException ( val ) ;
}
public sealed override void setByte ( object obj , byte b )
{
setInt ( obj , ( sbyte ) b ) ;
}
public sealed override void setChar ( object obj , char c )
{
setInt ( obj , c ) ;
}
public sealed override void setShort ( object obj , short s )
{
setInt ( obj , s ) ;
}
public sealed override int getInt ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void setInt ( object obj , int value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( int value )
{
return java . lang . Integer . valueOf ( value ) ;
}
}
private sealed class FloatField : FieldAccessor < float >
{
2015-08-26 07:17:56 -04:00
internal FloatField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
public sealed override double getDouble ( object obj )
{
return getFloat ( obj ) ;
}
public sealed override object get ( object obj )
{
return java . lang . Float . valueOf ( getFloat ( obj ) ) ;
}
public sealed override void set ( object obj , object val )
{
if ( val is java . lang . Float
| | val is java . lang . Byte
| | val is java . lang . Short
| | val is java . lang . Integer
| | val is java . lang . Long )
setFloat ( obj , ( ( java . lang . Number ) val ) . floatValue ( ) ) ;
else if ( val is java . lang . Character )
setFloat ( obj , ( ( java . lang . Character ) val ) . charValue ( ) ) ;
else
throw SetIllegalArgumentException ( val ) ;
}
public sealed override void setByte ( object obj , byte b )
{
setFloat ( obj , ( sbyte ) b ) ;
}
public sealed override void setChar ( object obj , char c )
{
setFloat ( obj , c ) ;
}
public sealed override void setShort ( object obj , short s )
{
setFloat ( obj , s ) ;
}
public sealed override void setInt ( object obj , int i )
{
setFloat ( obj , i ) ;
}
public sealed override void setLong ( object obj , long l )
{
setFloat ( obj , l ) ;
}
public sealed override float getFloat ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void setFloat ( object obj , float value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( float value )
{
return java . lang . Float . valueOf ( value ) ;
}
}
private sealed class LongField : FieldAccessor < long >
{
2015-08-26 07:17:56 -04:00
internal LongField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
public sealed override float getFloat ( object obj )
{
return getLong ( obj ) ;
}
public sealed override double getDouble ( object obj )
{
return getLong ( obj ) ;
}
public sealed override object get ( object obj )
{
return java . lang . Long . valueOf ( getLong ( obj ) ) ;
}
public sealed override void set ( object obj , object val )
{
if ( val is java . lang . Long
| | val is java . lang . Byte
| | val is java . lang . Short
| | val is java . lang . Integer )
setLong ( obj , ( ( java . lang . Number ) val ) . longValue ( ) ) ;
else if ( val is java . lang . Character )
setLong ( obj , ( ( java . lang . Character ) val ) . charValue ( ) ) ;
else
throw SetIllegalArgumentException ( val ) ;
}
public sealed override void setByte ( object obj , byte b )
{
setLong ( obj , ( sbyte ) b ) ;
}
public sealed override void setChar ( object obj , char c )
{
setLong ( obj , c ) ;
}
public sealed override void setShort ( object obj , short s )
{
setLong ( obj , s ) ;
}
public sealed override void setInt ( object obj , int i )
{
setLong ( obj , i ) ;
}
public sealed override long getLong ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void setLong ( object obj , long value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( long value )
{
return java . lang . Long . valueOf ( value ) ;
}
}
private sealed class DoubleField : FieldAccessor < double >
{
2015-08-26 07:17:56 -04:00
internal DoubleField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
public sealed override object get ( object obj )
{
return java . lang . Double . valueOf ( getDouble ( obj ) ) ;
}
public sealed override void set ( object obj , object val )
{
if ( val is java . lang . Double
| | val is java . lang . Float
| | val is java . lang . Byte
| | val is java . lang . Short
| | val is java . lang . Integer
| | val is java . lang . Long )
setDouble ( obj , ( ( java . lang . Number ) val ) . doubleValue ( ) ) ;
else if ( val is java . lang . Character )
setDouble ( obj , ( ( java . lang . Character ) val ) . charValue ( ) ) ;
else
throw SetIllegalArgumentException ( val ) ;
}
public sealed override void setByte ( object obj , byte b )
{
setDouble ( obj , ( sbyte ) b ) ;
}
public sealed override void setChar ( object obj , char c )
{
setDouble ( obj , c ) ;
}
public sealed override void setShort ( object obj , short s )
{
setDouble ( obj , s ) ;
}
public sealed override void setInt ( object obj , int i )
{
setDouble ( obj , i ) ;
}
public sealed override void setLong ( object obj , long l )
{
setDouble ( obj , l ) ;
}
public sealed override void setFloat ( object obj , float f )
{
setDouble ( obj , f ) ;
}
public sealed override double getDouble ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void setDouble ( object obj , double value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( double value )
{
return java . lang . Double . valueOf ( value ) ;
}
}
private sealed class ObjectField : FieldAccessor < object >
{
2015-08-26 07:17:56 -04:00
internal ObjectField ( FieldWrapper field , bool isFinal )
: base ( field , isFinal )
2014-08-13 10:39:27 +01:00
{
}
protected sealed override void CheckValue ( object value )
{
if ( value ! = null & & ! fw . FieldTypeWrapper . EnsureLoadable ( fw . DeclaringType . GetClassLoader ( ) ) . IsInstance ( value ) )
{
throw SetIllegalArgumentException ( value ) ;
}
}
public sealed override object get ( object obj )
{
try
{
return getter ( obj , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
public sealed override void set ( object obj , object value )
{
try
{
setter ( obj , value , this ) ;
}
catch ( FieldAccessException x )
{
throw new java . lang . IllegalAccessException ( ) . initCause ( x ) ;
}
}
protected sealed override object JavaBox ( object value )
{
return value ;
}
}
#if ! NO_REF_EMIT
private Delegate GenerateFastGetter ( Type delegateType , Type fieldType , FieldWrapper fw )
{
TypeWrapper fieldTypeWrapper ;
try
{
fieldTypeWrapper = fw . FieldTypeWrapper . EnsureLoadable ( fw . DeclaringType . GetClassLoader ( ) ) ;
fieldTypeWrapper . Finish ( ) ;
fw . DeclaringType . Finish ( ) ;
}
catch ( RetargetableJavaException x )
{
throw x . ToJava ( ) ;
}
fw . ResolveField ( ) ;
DynamicMethod dm = DynamicMethodUtils . Create ( "__<Getter>" , fw . DeclaringType . TypeAsBaseType , ! fw . IsPublic | | ! fw . DeclaringType . IsPublic , fieldType , new Type [ ] { typeof ( IReflectionException ) , typeof ( object ) , typeof ( object ) } ) ;
CodeEmitter ilgen = CodeEmitter . Create ( dm ) ;
if ( fw . IsStatic )
{
fw . EmitGet ( ilgen ) ;
fieldTypeWrapper . EmitConvSignatureTypeToStackType ( ilgen ) ;
}
else
{
ilgen . BeginExceptionBlock ( ) ;
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . Emit ( OpCodes . Castclass , fw . DeclaringType . TypeAsBaseType ) ;
fw . EmitGet ( ilgen ) ;
fieldTypeWrapper . EmitConvSignatureTypeToStackType ( ilgen ) ;
CodeEmitterLocal local = ilgen . DeclareLocal ( fieldType ) ;
ilgen . Emit ( OpCodes . Stloc , local ) ;
CodeEmitterLabel label = ilgen . DefineLabel ( ) ;
ilgen . EmitLeave ( label ) ;
ilgen . BeginCatchBlock ( typeof ( InvalidCastException ) ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . Emit ( OpCodes . Callvirt , typeof ( IReflectionException ) . GetMethod ( "GetIllegalArgumentException" ) ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . EndExceptionBlock ( ) ;
ilgen . MarkLabel ( label ) ;
ilgen . Emit ( OpCodes . Ldloc , local ) ;
}
ilgen . Emit ( OpCodes . Ret ) ;
ilgen . DoEmit ( ) ;
return dm . CreateDelegate ( delegateType , this ) ;
}
private Delegate GenerateFastSetter ( Type delegateType , Type fieldType , FieldWrapper fw )
{
TypeWrapper fieldTypeWrapper ;
try
{
fieldTypeWrapper = fw . FieldTypeWrapper . EnsureLoadable ( fw . DeclaringType . GetClassLoader ( ) ) ;
fieldTypeWrapper . Finish ( ) ;
fw . DeclaringType . Finish ( ) ;
}
catch ( RetargetableJavaException x )
{
throw x . ToJava ( ) ;
}
fw . ResolveField ( ) ;
DynamicMethod dm = DynamicMethodUtils . Create ( "__<Setter>" , fw . DeclaringType . TypeAsBaseType , ! fw . IsPublic | | ! fw . DeclaringType . IsPublic , null , new Type [ ] { typeof ( IReflectionException ) , typeof ( object ) , fieldType , typeof ( object ) } ) ;
CodeEmitter ilgen = CodeEmitter . Create ( dm ) ;
if ( fw . IsStatic )
{
if ( fieldType = = typeof ( object ) )
{
ilgen . BeginExceptionBlock ( ) ;
ilgen . Emit ( OpCodes . Ldarg_2 ) ;
fieldTypeWrapper . EmitCheckcast ( ilgen ) ;
fieldTypeWrapper . EmitConvStackTypeToSignatureType ( ilgen , null ) ;
fw . EmitSet ( ilgen ) ;
CodeEmitterLabel label = ilgen . DefineLabel ( ) ;
ilgen . EmitLeave ( label ) ;
ilgen . BeginCatchBlock ( typeof ( InvalidCastException ) ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . Emit ( OpCodes . Callvirt , typeof ( IReflectionException ) . GetMethod ( "SetIllegalArgumentException" ) ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . EndExceptionBlock ( ) ;
ilgen . MarkLabel ( label ) ;
}
else
{
ilgen . Emit ( OpCodes . Ldarg_2 ) ;
fw . EmitSet ( ilgen ) ;
}
}
else
{
ilgen . BeginExceptionBlock ( ) ;
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . Emit ( OpCodes . Castclass , fw . DeclaringType . TypeAsBaseType ) ;
ilgen . Emit ( OpCodes . Ldarg_2 ) ;
if ( fieldType = = typeof ( object ) )
{
fieldTypeWrapper . EmitCheckcast ( ilgen ) ;
}
fieldTypeWrapper . EmitConvStackTypeToSignatureType ( ilgen , null ) ;
fw . EmitSet ( ilgen ) ;
CodeEmitterLabel label = ilgen . DefineLabel ( ) ;
ilgen . EmitLeave ( label ) ;
ilgen . BeginCatchBlock ( typeof ( InvalidCastException ) ) ;
ilgen . Emit ( OpCodes . Ldarg_0 ) ;
ilgen . Emit ( OpCodes . Ldarg_1 ) ;
ilgen . Emit ( OpCodes . Callvirt , typeof ( IReflectionException ) . GetMethod ( "SetIllegalArgumentException" ) ) ;
ilgen . Emit ( OpCodes . Throw ) ;
ilgen . EndExceptionBlock ( ) ;
ilgen . MarkLabel ( label ) ;
}
ilgen . Emit ( OpCodes . Ret ) ;
ilgen . DoEmit ( ) ;
return dm . CreateDelegate ( delegateType , this ) ;
}
#endif // !NO_REF_EMIT
2015-08-26 07:17:56 -04:00
internal static FieldAccessorImplBase Create ( FieldWrapper field , bool isFinal )
2014-08-13 10:39:27 +01:00
{
TypeWrapper type = field . FieldTypeWrapper ;
if ( type . IsPrimitive )
{
if ( type = = PrimitiveTypeWrapper . BYTE )
{
2015-08-26 07:17:56 -04:00
return new ByteField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
if ( type = = PrimitiveTypeWrapper . BOOLEAN )
{
2015-08-26 07:17:56 -04:00
return new BooleanField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
if ( type = = PrimitiveTypeWrapper . CHAR )
{
2015-08-26 07:17:56 -04:00
return new CharField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
if ( type = = PrimitiveTypeWrapper . SHORT )
{
2015-08-26 07:17:56 -04:00
return new ShortField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
if ( type = = PrimitiveTypeWrapper . INT )
{
2015-08-26 07:17:56 -04:00
return new IntField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
if ( type = = PrimitiveTypeWrapper . FLOAT )
{
2015-08-26 07:17:56 -04:00
return new FloatField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
if ( type = = PrimitiveTypeWrapper . LONG )
{
2015-08-26 07:17:56 -04:00
return new LongField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
if ( type = = PrimitiveTypeWrapper . DOUBLE )
{
2015-08-26 07:17:56 -04:00
return new DoubleField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
throw new InvalidOperationException ( "field type: " + type ) ;
}
else
{
2015-08-26 07:17:56 -04:00
return new ObjectField ( field , isFinal ) ;
2014-08-13 10:39:27 +01:00
}
}
}
#endif
public static sun . reflect . FieldAccessor newFieldAccessor ( object thisFactory , java . lang . reflect . Field field , bool overrideAccessCheck )
{
#if FIRST_PASS
return null ;
#else
2015-08-26 07:17:56 -04:00
// we look at the modifiers of the Field object to allow Unsafe to give us a fake Field take doesn't have the final flag set
int modifiers = field . getModifiers ( ) ;
bool isStatic = java . lang . reflect . Modifier . isStatic ( modifiers ) ;
bool isFinal = java . lang . reflect . Modifier . isFinal ( modifiers ) ;
return FieldAccessorImplBase . Create ( FieldWrapper . FromField ( field ) , isFinal & & ( ! overrideAccessCheck | | isStatic ) ) ;
2014-08-13 10:39:27 +01:00
#endif
}
#if ! FIRST_PASS
internal static sun . reflect . FieldAccessor NewFieldAccessorJNI ( FieldWrapper field )
{
2015-08-26 07:17:56 -04:00
return FieldAccessorImplBase . Create ( field , false ) ;
2014-08-13 10:39:27 +01:00
}
#endif
public static sun . reflect . MethodAccessor newMethodAccessor ( object thisFactory , java . lang . reflect . Method method )
{
#if FIRST_PASS
return null ;
#else
2015-08-26 07:17:56 -04:00
MethodWrapper mw = MethodWrapper . FromExecutable ( method ) ;
2014-08-13 10:39:27 +01:00
#if ! NO_REF_EMIT
if ( ! mw . IsDynamicOnly )
{
return new FastMethodAccessorImpl ( mw ) ;
}
#endif
return new MethodAccessorImpl ( mw ) ;
#endif
}
public static sun . reflect . ConstructorAccessor newConstructorAccessor0 ( object thisFactory , java . lang . reflect . Constructor constructor )
{
#if FIRST_PASS
return null ;
#else
2015-08-26 07:17:56 -04:00
MethodWrapper mw = MethodWrapper . FromExecutable ( constructor ) ;
2014-08-13 10:39:27 +01:00
if ( ActivatorConstructorAccessor . IsSuitable ( mw ) )
{
// we special case public default constructors, because in that case using Activator.CreateInstance()
// is almost as fast as FastConstructorAccessorImpl, but it saves us significantly in working set and
// startup time (because often during startup a sun.nio.cs.* encoder is instantiated using reflection)
return new ActivatorConstructorAccessor ( mw ) ;
}
else
{
#if NO_REF_EMIT
return new ConstructorAccessorImpl ( mw ) ;
#else
return new FastConstructorAccessorImpl ( constructor ) ;
#endif
}
#endif
}
public static sun . reflect . ConstructorAccessor newConstructorAccessorForSerialization ( java . lang . Class classToInstantiate , java . lang . reflect . Constructor constructorToCall )
{
#if FIRST_PASS
return null ;
#else
try
{
#if NO_REF_EMIT
return new SerializationConstructorAccessorImpl ( constructorToCall , classToInstantiate ) ;
#else
return new FastSerializationConstructorAccessorImpl ( constructorToCall , classToInstantiate ) ;
#endif
}
catch ( SecurityException x )
{
throw new java . lang . SecurityException ( x . Message , ikvm . runtime . Util . mapException ( x ) ) ;
}
#endif
}
}
static class Java_sun_reflect_ConstantPool
{
public static int getSize0 ( object thisConstantPool , object constantPoolOop )
{
throw new NotImplementedException ( ) ;
}
public static object getClassAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static object getClassAtIfLoaded0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static object getMethodAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static object getMethodAtIfLoaded0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static object getFieldAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static object getFieldAtIfLoaded0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static string [ ] getMemberRefInfoAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static int getIntAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static long getLongAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static float getFloatAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static double getDoubleAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static string getStringAt0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
public static string getUTF8At0 ( object thisConstantPool , object constantPoolOop , int index )
{
throw new NotImplementedException ( ) ;
}
}