diff options
Diffstat (limited to 'external/ikvm/runtime/openjdk/sun.reflect.cs')
-rw-r--r-- | external/ikvm/runtime/openjdk/sun.reflect.cs | 2293 |
1 files changed, 2293 insertions, 0 deletions
diff --git a/external/ikvm/runtime/openjdk/sun.reflect.cs b/external/ikvm/runtime/openjdk/sun.reflect.cs new file mode 100644 index 0000000000..a80d4f37dd --- /dev/null +++ b/external/ikvm/runtime/openjdk/sun.reflect.cs @@ -0,0 +1,2293 @@ +/* + Copyright (C) 2007-2013 Jeroen Frijters + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + 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; + +namespace IKVM.Internal +{ +#if !FIRST_PASS + public interface IReflectionException + { + java.lang.IllegalArgumentException GetIllegalArgumentException(object obj); + java.lang.IllegalArgumentException SetIllegalArgumentException(object obj); + } +#endif + + sealed class State + { + internal int Value; + } +} + +static class Java_sun_reflect_Reflection +{ +#if CLASSGC + private static readonly ConditionalWeakTable<MethodBase, State> isHideFromJavaCache = new ConditionalWeakTable<MethodBase, State>(); + + internal static bool IsHideFromJava(MethodBase mb) + { + State state = isHideFromJavaCache.GetValue(mb, delegate { return new State(); }); + if (state.Value == 0) + { + state.Value = IsHideFromJavaImpl(mb); + } + return state.Value == 1; + } + + private static int IsHideFromJavaImpl(MethodBase mb) + { + if (mb.Name.StartsWith("__<", StringComparison.Ordinal)) + { + return 1; + } + if (mb.IsDefined(typeof(IKVM.Attributes.HideFromJavaAttribute), false) || mb.IsDefined(typeof(IKVM.Attributes.HideFromReflectionAttribute), false)) + { + return 1; + } + return 2; + } +#else + private static readonly Dictionary<RuntimeMethodHandle, bool> isHideFromJavaCache = new Dictionary<RuntimeMethodHandle, bool>(); + + internal static bool IsHideFromJava(MethodBase mb) + { + if (mb.Name.StartsWith("__<", StringComparison.Ordinal)) + { + return true; + } + RuntimeMethodHandle handle; + try + { + handle = mb.MethodHandle; + } + catch (InvalidOperationException) + { + // DynamicMethods don't have a RuntimeMethodHandle and we always want to hide them anyway + return true; + } + catch (NotSupportedException) + { + // DynamicMethods don't have a RuntimeMethodHandle and we always want to hide them anyway + return true; + } + lock (isHideFromJavaCache) + { + bool cached; + if (isHideFromJavaCache.TryGetValue(handle, out cached)) + { + return cached; + } + } + bool isHide = mb.IsDefined(typeof(IKVM.Attributes.HideFromJavaAttribute), false) || mb.IsDefined(typeof(IKVM.Attributes.HideFromReflectionAttribute), false); + lock (isHideFromJavaCache) + { + isHideFromJavaCache[handle] = isHide; + } + return isHide; + } +#endif + + // 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. + public static object getCallerClass(int realFramesToSkip) + { +#if FIRST_PASS + return null; +#else + int i = 3; + if (realFramesToSkip <= 1) + { + i = 1; + realFramesToSkip = Math.Max(realFramesToSkip + 2, 2); + } + realFramesToSkip--; + for (; ; ) + { + MethodBase method = new StackFrame(i++, false).GetMethod(); + if (method == null) + { + return null; + } + Type type = method.DeclaringType; + // NOTE these checks should be the same as the ones in SecurityManager.getClassContext + if (IsHideFromJava(method) + || 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)) + { + continue; + } + if (--realFramesToSkip == 0) + { + return ClassLoaderWrapper.GetWrapperFromType(type).ClassObject; + } + } +#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; + MethodWrapper mw = MethodWrapper.FromConstructor(constructorToCall); + 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) + { + MethodWrapper mw = MethodWrapper.FromConstructor(constructor); + 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) + { + MethodWrapper constructor = MethodWrapper.FromConstructor(constructorToCall); + 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; + } + } + } + + private FieldAccessorImplBase(FieldWrapper fw, bool overrideAccessCheck) + { + this.fw = fw; + isFinal = (!overrideAccessCheck || fw.IsStatic) && fw.IsFinal; + } + + private string GetQualifiedFieldName() + { + return fw.DeclaringType.Name + "." + fw.Name; + } + + private string GetFieldTypeName() + { + return fw.FieldTypeWrapper.ClassObject.getName(); + } + + 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; + + internal FieldAccessor(FieldWrapper fw, bool overrideAccessCheck) + : base(fw, overrideAccessCheck) + { + 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> + { + internal ByteField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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> + { + internal BooleanField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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> + { + internal CharField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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> + { + internal ShortField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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> + { + internal IntField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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> + { + internal FloatField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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> + { + internal LongField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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> + { + internal DoubleField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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> + { + internal ObjectField(FieldWrapper field, bool overrideAccessCheck) + : base(field, overrideAccessCheck) + { + } + + 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 + + internal static FieldAccessorImplBase Create(FieldWrapper field, bool overrideAccessCheck) + { + TypeWrapper type = field.FieldTypeWrapper; + if (type.IsPrimitive) + { + if (type == PrimitiveTypeWrapper.BYTE) + { + return new ByteField(field, overrideAccessCheck); + } + if (type == PrimitiveTypeWrapper.BOOLEAN) + { + return new BooleanField(field, overrideAccessCheck); + } + if (type == PrimitiveTypeWrapper.CHAR) + { + return new CharField(field, overrideAccessCheck); + } + if (type == PrimitiveTypeWrapper.SHORT) + { + return new ShortField(field, overrideAccessCheck); + } + if (type == PrimitiveTypeWrapper.INT) + { + return new IntField(field, overrideAccessCheck); + } + if (type == PrimitiveTypeWrapper.FLOAT) + { + return new FloatField(field, overrideAccessCheck); + } + if (type == PrimitiveTypeWrapper.LONG) + { + return new LongField(field, overrideAccessCheck); + } + if (type == PrimitiveTypeWrapper.DOUBLE) + { + return new DoubleField(field, overrideAccessCheck); + } + throw new InvalidOperationException("field type: " + type); + } + else + { + return new ObjectField(field, overrideAccessCheck); + } + } + } +#endif + + public static sun.reflect.FieldAccessor newFieldAccessor(object thisFactory, java.lang.reflect.Field field, bool overrideAccessCheck) + { +#if FIRST_PASS + return null; +#else + return FieldAccessorImplBase.Create(FieldWrapper.FromField(field), overrideAccessCheck); +#endif + } + +#if !FIRST_PASS + internal static sun.reflect.FieldAccessor NewFieldAccessorJNI(FieldWrapper field) + { + return FieldAccessorImplBase.Create(field, true); + } +#endif + + public static sun.reflect.MethodAccessor newMethodAccessor(object thisFactory, java.lang.reflect.Method method) + { +#if FIRST_PASS + return null; +#else + MethodWrapper mw = MethodWrapper.FromMethod(method); +#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 + MethodWrapper mw = MethodWrapper.FromConstructor(constructor); + 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(); + } +} |