static ProxyGenerator() { ClassLoaderWrapper bootClassLoader = ClassLoaderWrapper.GetBootstrapClassLoader(); proxyClass = bootClassLoader.LoadClassByDottedNameFast("java.lang.reflect.Proxy"); errorClass = bootClassLoader.LoadClassByDottedNameFast("java.lang.Error"); runtimeExceptionClass = bootClassLoader.LoadClassByDottedNameFast("java.lang.RuntimeException"); undeclaredThrowableExceptionConstructor = bootClassLoader.LoadClassByDottedNameFast("java.lang.reflect.UndeclaredThrowableException").GetMethodWrapper("<init>", "(Ljava.lang.Throwable;)V", false); undeclaredThrowableExceptionConstructor.Link(); invocationHandlerField = proxyClass.GetFieldWrapper("h", "Ljava.lang.reflect.InvocationHandler;"); invocationHandlerField.Link(); javaLangReflectMethod = bootClassLoader.LoadClassByDottedNameFast("java.lang.reflect.Method"); javaLangNoSuchMethodException = bootClassLoader.LoadClassByDottedNameFast("java.lang.NoSuchMethodException"); javaLangNoClassDefFoundErrorConstructor = bootClassLoader.LoadClassByDottedNameFast("java.lang.NoClassDefFoundError").GetMethodWrapper("<init>", "(Ljava.lang.String;)V", false); javaLangNoClassDefFoundErrorConstructor.Link(); javaLangThrowable_getMessage = bootClassLoader.LoadClassByDottedNameFast("java.lang.Throwable").GetMethodWrapper("getMessage", "()Ljava.lang.String;", false); javaLangThrowable_getMessage.Link(); javaLangClass_getMethod = CoreClasses.java.lang.Class.Wrapper.GetMethodWrapper("getMethod", "(Ljava.lang.String;[Ljava.lang.Class;)Ljava.lang.reflect.Method;", false); javaLangClass_getMethod.Link(); invocationHandlerClass = bootClassLoader.LoadClassByDottedNameFast("java.lang.reflect.InvocationHandler"); invokeMethod = invocationHandlerClass.GetMethodWrapper("invoke", "(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object;", false); proxyConstructor = proxyClass.GetMethodWrapper("<init>", "(Ljava.lang.reflect.InvocationHandler;)V", false); proxyConstructor.Link(); hashCodeMethod = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper("hashCode", "()I", false); equalsMethod = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper("equals", "(Ljava.lang.Object;)Z", false); toStringMethod = CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper("toString", "()Ljava.lang.String;", false); }
internal static void InlineJsrs(ClassLoaderWrapper classLoader, MethodWrapper mw, ClassFile classFile, ClassFile.Method m) { JsrInliner inliner; do { ClassFile.Method.Instruction[] codeCopy = (ClassFile.Method.Instruction[])m.Instructions.Clone(); InstructionFlags[] flags = new InstructionFlags[codeCopy.Length]; JsrMethodAnalyzer ma = new JsrMethodAnalyzer(mw, classFile, m, classLoader, flags); inliner = new JsrInliner(codeCopy, flags, m, ma); } while (inliner.InlineJsrs()); }
static Boxer() { ClassLoaderWrapper bootClassLoader = ClassLoaderWrapper.GetBootstrapClassLoader(); javaLangByte = bootClassLoader.LoadClassByDottedNameFast("java.lang.Byte"); byteValue = javaLangByte.GetMethodWrapper("byteValue", "()B", false); byteValue.Link(); valueOfByte = javaLangByte.GetMethodWrapper("valueOf", "(B)Ljava.lang.Byte;", false); valueOfByte.Link(); javaLangBoolean = bootClassLoader.LoadClassByDottedNameFast("java.lang.Boolean"); booleanValue = javaLangBoolean.GetMethodWrapper("booleanValue", "()Z", false); booleanValue.Link(); valueOfBoolean = javaLangBoolean.GetMethodWrapper("valueOf", "(Z)Ljava.lang.Boolean;", false); valueOfBoolean.Link(); javaLangShort = bootClassLoader.LoadClassByDottedNameFast("java.lang.Short"); shortValue = javaLangShort.GetMethodWrapper("shortValue", "()S", false); shortValue.Link(); valueOfShort = javaLangShort.GetMethodWrapper("valueOf", "(S)Ljava.lang.Short;", false); valueOfShort.Link(); javaLangCharacter = bootClassLoader.LoadClassByDottedNameFast("java.lang.Character"); charValue = javaLangCharacter.GetMethodWrapper("charValue", "()C", false); charValue.Link(); valueOfCharacter = javaLangCharacter.GetMethodWrapper("valueOf", "(C)Ljava.lang.Character;", false); valueOfCharacter.Link(); javaLangInteger = bootClassLoader.LoadClassByDottedNameFast("java.lang.Integer"); intValue = javaLangInteger.GetMethodWrapper("intValue", "()I", false); intValue.Link(); valueOfInteger = javaLangInteger.GetMethodWrapper("valueOf", "(I)Ljava.lang.Integer;", false); valueOfInteger.Link(); javaLangFloat = bootClassLoader.LoadClassByDottedNameFast("java.lang.Float"); floatValue = javaLangFloat.GetMethodWrapper("floatValue", "()F", false); floatValue.Link(); valueOfFloat = javaLangFloat.GetMethodWrapper("valueOf", "(F)Ljava.lang.Float;", false); valueOfFloat.Link(); javaLangLong = bootClassLoader.LoadClassByDottedNameFast("java.lang.Long"); longValue = javaLangLong.GetMethodWrapper("longValue", "()J", false); longValue.Link(); valueOfLong = javaLangLong.GetMethodWrapper("valueOf", "(J)Ljava.lang.Long;", false); valueOfLong.Link(); javaLangDouble = bootClassLoader.LoadClassByDottedNameFast("java.lang.Double"); doubleValue = javaLangDouble.GetMethodWrapper("doubleValue", "()D", false); doubleValue.Link(); valueOfDouble = javaLangDouble.GetMethodWrapper("valueOf", "(D)Ljava.lang.Double;", false); valueOfDouble.Link(); }
internal DynamicPropertyFieldWrapper(TypeWrapper declaringType, ClassFile.Field fld) : base(declaringType, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal), null) { getter = GetMethod(fld.PropertyGetter, "()" + fld.Signature, fld.IsStatic); setter = GetMethod(fld.PropertySetter, "(" + fld.Signature + ")V", fld.IsStatic); }
internal IKVM.Internal.MapXml.ReplaceMethodCall[] GetReplacedMethodsFor(MethodWrapper mw) { if(mapxml_ReplacedMethods == null) { return null; } IKVM.Internal.MapXml.ReplaceMethodCall[] rmc; mapxml_ReplacedMethods.TryGetValue(new MethodKey(mw.DeclaringType.Name, mw.Name, mw.Signature), out rmc); return rmc; }
private static MethodAttributes GetPropertyMethodAttributes(MethodWrapper mw, bool final) { MethodAttributes attribs = MethodAttributes.HideBySig; if(mw.IsStatic) { attribs |= MethodAttributes.Static; } else { // NOTE in order for IntelliSense to consider the property a "real" property, // the getter and setter methods need to have substantially the same method attributes, // so we may need to look at our peer to determine whether we should be final // or not (and vice versa). attribs |= MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride; if(final) { attribs |= MethodAttributes.Final; } } // TODO what happens if accessibility doesn't match our peer? if(mw.IsPublic) { attribs |= MethodAttributes.Public; } else if(mw.IsProtected) { attribs |= MethodAttributes.FamORAssem; } else if(mw.IsPrivate) { attribs |= MethodAttributes.Private; } else { attribs |= MethodAttributes.Assembly; } return attribs; }
protected override void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, FieldWrapper[] fields, MethodWrapper[] methods) { Dictionary<string, IKVM.Internal.MapXml.Class> mapxml = classLoader.GetMapXmlClasses(); if(mapxml != null) { IKVM.Internal.MapXml.Class clazz; if(mapxml.TryGetValue(classFile.Name, out clazz)) { if(clazz.Attributes != null) { PublishAttributes(typeBuilder, clazz); } if(clazz.Properties != null) { PublishProperties(typeBuilder, clazz); } if(clazz.Fields != null) { foreach(IKVM.Internal.MapXml.Field field in clazz.Fields) { if(field.Attributes != null) { foreach(FieldWrapper fw in fields) { if(fw.Name == field.Name && fw.Signature == field.Sig) { FieldBuilder fb = fw.GetField() as FieldBuilder; if(fb != null) { foreach(IKVM.Internal.MapXml.Attribute attr in field.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, fb, attr); } } } } } } } if(clazz.Constructors != null) { // HACK this isn't the right place to do this, but for now it suffices foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors) { // are we adding a new constructor? if(GetMethodWrapper(StringConstants.INIT, constructor.Sig, false) == null) { if(constructor.body == null) { Console.Error.WriteLine("Error: Constructor {0}.<init>{1} in xml remap file doesn't have a body.", clazz.Name, constructor.Sig); continue; } bool setmodifiers = false; MethodAttributes attribs = 0; MapModifiers(constructor.Modifiers, true, out setmodifiers, ref attribs); Type returnType; Type[] parameterTypes; MapSignature(constructor.Sig, out returnType, out parameterTypes); MethodBuilder cb = ReflectUtil.DefineConstructor(typeBuilder, attribs, parameterTypes); if(setmodifiers) { AttributeHelper.SetModifiers(cb, (Modifiers)constructor.Modifiers, false); } CompilerClassLoader.AddDeclaredExceptions(cb, constructor.throws); CodeEmitter ilgen = CodeEmitter.Create(cb); constructor.Emit(classLoader, ilgen); ilgen.DoEmit(); if(constructor.Attributes != null) { foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, cb, attr); } } } } foreach(IKVM.Internal.MapXml.Constructor constructor in clazz.Constructors) { if(constructor.Attributes != null) { foreach(MethodWrapper mw in methods) { if(mw.Name == "<init>" && mw.Signature == constructor.Sig) { MethodBuilder mb = mw.GetMethod() as MethodBuilder; if(mb != null) { foreach(IKVM.Internal.MapXml.Attribute attr in constructor.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, mb, attr); } } } } } } } if(clazz.Methods != null) { // HACK this isn't the right place to do this, but for now it suffices foreach(IKVM.Internal.MapXml.Method method in clazz.Methods) { // are we adding a new method? if(GetMethodWrapper(method.Name, method.Sig, false) == null) { if(method.body == null) { Console.Error.WriteLine("Error: Method {0}.{1}{2} in xml remap file doesn't have a body.", clazz.Name, method.Name, method.Sig); continue; } bool setmodifiers = false; MethodAttributes attribs = method.MethodAttributes; MapModifiers(method.Modifiers, false, out setmodifiers, ref attribs); Type returnType; Type[] parameterTypes; MapSignature(method.Sig, out returnType, out parameterTypes); MethodBuilder mb = typeBuilder.DefineMethod(method.Name, attribs, returnType, parameterTypes); if(setmodifiers) { AttributeHelper.SetModifiers(mb, (Modifiers)method.Modifiers, false); } if(method.@override != null) { MethodWrapper mw = GetClassLoader().LoadClassByDottedName([email protected]).GetMethodWrapper([email protected], method.Sig, true); mw.Link(); typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); } CompilerClassLoader.AddDeclaredExceptions(mb, method.throws); CodeEmitter ilgen = CodeEmitter.Create(mb); method.Emit(classLoader, ilgen); ilgen.DoEmit(); if(method.Attributes != null) { foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, mb, attr); } } } } foreach(IKVM.Internal.MapXml.Method method in clazz.Methods) { if(method.Attributes != null) { foreach(MethodWrapper mw in methods) { if(mw.Name == method.Name && mw.Signature == method.Sig) { MethodBuilder mb = mw.GetMethod() as MethodBuilder; if(mb != null) { foreach(IKVM.Internal.MapXml.Attribute attr in method.Attributes) { AttributeHelper.SetCustomAttribute(classLoader, mb, attr); } } } } } } } if(clazz.Interfaces != null) { foreach(IKVM.Internal.MapXml.Interface iface in clazz.Interfaces) { TypeWrapper tw = GetClassLoader().LoadClassByDottedName(iface.Name); // NOTE since this interface won't be part of the list in the ImplementAttribute, // it won't be visible from Java that the type implements this interface. typeBuilder.AddInterfaceImplementation(tw.TypeAsBaseType); if(iface.Methods != null) { foreach(IKVM.Internal.MapXml.Method m in iface.Methods) { MethodWrapper mw = tw.GetMethodWrapper(m.Name, m.Sig, false); if(mw == null) { throw new InvalidOperationException("Method " + m.Name + m.Sig + " not found in interface " + tw.Name); } mw.Link(); MethodBuilder mb = mw.GetDefineMethodHelper().DefineMethod(this, typeBuilder, tw.Name + "/" + m.Name, MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.CheckAccessOnOverride); AttributeHelper.HideFromJava(mb); typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod()); CodeEmitter ilgen = CodeEmitter.Create(mb); m.Emit(classLoader, ilgen); ilgen.DoEmit(); } } } } } } }
internal MethodWrapper ReplaceMethodWrapper(MethodWrapper mw) { if (replacedMethods != null) { foreach (MethodWrapper r in replacedMethods) { if (mw.DeclaringType == r.DeclaringType && mw.Name == r.Name && mw.Signature == r.Signature) { return r; } } } return mw; }
internal WorkaroundBaseClass(AotTypeWrapper wrapper, TypeBuilder typeBuilder, MethodWrapper[] methods) { this.wrapper = wrapper; this.typeBuilder = typeBuilder; this.methods = methods; }
internal BaseFinalMethodWrapper(DotNetTypeWrapper tw, MethodWrapper m) : base(tw, m.Name, m.Signature, null, null, null, (m.Modifiers & ~Modifiers.Abstract) | Modifiers.Final, MemberFlags.None) { this.m = m; }
protected override void LazyPublishMembers() { // special support for enums if (type.IsEnum) { Type underlyingType = EnumHelper.GetUnderlyingType(type); Type javaUnderlyingType; if (underlyingType == Types.SByte) { javaUnderlyingType = Types.Byte; } else if (underlyingType == Types.UInt16) { javaUnderlyingType = Types.Int16; } else if (underlyingType == Types.UInt32) { javaUnderlyingType = Types.Int32; } else if (underlyingType == Types.UInt64) { javaUnderlyingType = Types.Int64; } else { javaUnderlyingType = underlyingType; } TypeWrapper fieldType = ClassLoaderWrapper.GetWrapperFromType(javaUnderlyingType); FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static); List<FieldWrapper> fieldsList = new List<FieldWrapper>(); for (int i = 0; i < fields.Length; i++) { if (fields[i].FieldType == type) { string name = fields[i].Name; if (name == "Value") { name = "_Value"; } else if (name.StartsWith("_") && name.EndsWith("Value")) { name = "_" + name; } object val = EnumHelper.GetPrimitiveValue(underlyingType, fields[i].GetRawConstantValue()); fieldsList.Add(new ConstantFieldWrapper(this, fieldType, name, fieldType.SigName, Modifiers.Public | Modifiers.Static | Modifiers.Final, fields[i], val, MemberFlags.None)); } } fieldsList.Add(new EnumValueFieldWrapper(this, fieldType)); SetFields(fieldsList.ToArray()); SetMethods(new MethodWrapper[] { new EnumWrapMethodWrapper(this, fieldType) }); } else { List<FieldWrapper> fieldsList = new List<FieldWrapper>(); FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); for (int i = 0; i < fields.Length; i++) { // TODO for remapped types, instance fields need to be converted to static getter/setter methods if (fields[i].FieldType.IsPointer) { // skip, pointer fields are not supported } else { // TODO handle name/signature clash fieldsList.Add(CreateFieldWrapperDotNet(AttributeHelper.GetModifiers(fields[i], true).Modifiers, fields[i].Name, fields[i].FieldType, fields[i])); } } SetFields(fieldsList.ToArray()); Dictionary<string, MethodWrapper> methodsList = new Dictionary<string, MethodWrapper>(); // special case for delegate constructors! if (IsDelegate(type)) { TypeWrapper iface = InnerClasses[0]; DelegateMethodWrapper mw = new DelegateMethodWrapper(this, (DelegateInnerClassTypeWrapper)iface); methodsList.Add(mw.Name + mw.Signature, mw); } // add a protected default constructor to MulticastDelegate to make it easier to define a delegate in Java if (type == Types.MulticastDelegate) { methodsList.Add("<init>()V", new MulticastDelegateCtorMethodWrapper(this)); } ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); for (int i = 0; i < constructors.Length; i++) { string name; string sig; TypeWrapper[] args; TypeWrapper ret; if (MakeMethodDescriptor(constructors[i], out name, out sig, out args, out ret)) { MethodWrapper mw = CreateMethodWrapper(name, sig, args, ret, constructors[i], false); string key = mw.Name + mw.Signature; if (!methodsList.ContainsKey(key)) { methodsList.Add(key, mw); } } } if (type.IsValueType && !methodsList.ContainsKey("<init>()V")) { // Value types have an implicit default ctor methodsList.Add("<init>()V", new ValueTypeDefaultCtor(this)); } MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); for (int i = 0; i < methods.Length; i++) { if (methods[i].IsStatic && type.IsInterface) { // skip, Java cannot deal with static methods on interfaces } else { string name; string sig; TypeWrapper[] args; TypeWrapper ret; if (MakeMethodDescriptor(methods[i], out name, out sig, out args, out ret)) { if (!methods[i].IsStatic && !methods[i].IsPrivate && BaseTypeWrapper != null) { MethodWrapper baseMethod = BaseTypeWrapper.GetMethodWrapper(name, sig, true); if (baseMethod != null && baseMethod.IsFinal && !baseMethod.IsStatic && !baseMethod.IsPrivate) { continue; } } MethodWrapper mw = CreateMethodWrapper(name, sig, args, ret, methods[i], false); string key = mw.Name + mw.Signature; MethodWrapper existing; methodsList.TryGetValue(key, out existing); if (existing == null || existing is ByRefMethodWrapper) { methodsList[key] = mw; } } else if (methods[i].IsAbstract) { SetHasUnsupportedAbstractMethods(); } } } // make sure that all the interface methods that we implement are available as public methods, // otherwise javac won't like the class. if (!type.IsInterface) { Type[] interfaces = type.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { // we only handle public (or nested public) types, because we're potentially adding a // method that should be callable by anyone through the interface if (interfaces[i].IsVisible) { if (ClassLoaderWrapper.IsRemappedType(interfaces[i])) { TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(interfaces[i]); foreach (MethodWrapper mw in tw.GetMethods()) { // HACK we need to link here, because during a core library build we might reference java.lang.AutoCloseable (via IDisposable) before it has been linked mw.Link(); InterfaceMethodStubHelper(methodsList, mw.GetMethod(), mw.Name, mw.Signature, mw.GetParameters(), mw.ReturnType); } } InterfaceMapping map = type.GetInterfaceMap(interfaces[i]); for (int j = 0; j < map.InterfaceMethods.Length; j++) { if (map.TargetMethods[j] == null || ((!map.TargetMethods[j].IsPublic || map.TargetMethods[j].Name != map.InterfaceMethods[j].Name) && map.TargetMethods[j].DeclaringType == type)) { string name; string sig; TypeWrapper[] args; TypeWrapper ret; if (MakeMethodDescriptor(map.InterfaceMethods[j], out name, out sig, out args, out ret)) { InterfaceMethodStubHelper(methodsList, map.InterfaceMethods[j], name, sig, args, ret); } } } } } } // for non-final remapped types, we need to add all the virtual methods in our alter ego (which // appears as our base class) and make them final (to prevent Java code from overriding these // methods, which don't really exist). if (ClassLoaderWrapper.IsRemappedType(type) && !type.IsSealed && !type.IsInterface) { TypeWrapper baseTypeWrapper = this.BaseTypeWrapper; while (baseTypeWrapper != null) { foreach (MethodWrapper m in baseTypeWrapper.GetMethods()) { if (!m.IsStatic && !m.IsFinal && (m.IsPublic || m.IsProtected) && m.Name != "<init>") { string key = m.Name + m.Signature; if (!methodsList.ContainsKey(key)) { if (m.IsProtected) { if (m.Name == "finalize" && m.Signature == "()V") { methodsList.Add(key, new FinalizeMethodWrapper(this)); } else if (m.Name == "clone" && m.Signature == "()Ljava.lang.Object;") { methodsList.Add(key, new CloneMethodWrapper(this)); } else { // there should be a special MethodWrapper for this method throw new InvalidOperationException("Missing protected method support for " + baseTypeWrapper.Name + "::" + m.Name + m.Signature); } } else { methodsList.Add(key, new BaseFinalMethodWrapper(this, m)); } } } } baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper; } } #if !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS // support serializing .NET exceptions (by replacing them with a placeholder exception) if (typeof(Exception).IsAssignableFrom(type) && !typeof(java.io.Serializable.__Interface).IsAssignableFrom(type) && !methodsList.ContainsKey("writeReplace()Ljava.lang.Object;")) { methodsList.Add("writeReplace()Ljava.lang.Object;", new ExceptionWriteReplaceMethodWrapper(this)); } #endif // !STATIC_COMPILER && !STUB_GENERATOR && !FIRST_PASS MethodWrapper[] methodArray = new MethodWrapper[methodsList.Count]; methodsList.Values.CopyTo(methodArray, 0); SetMethods(methodArray); } }
internal BaseFinalMethodWrapper(DotNetTypeWrapper tw, MethodWrapper m) : base(tw, m.Name, m.Signature, m.GetMethod(), m.ReturnType, m.GetParameters(), (m.Modifiers & ~Modifiers.Abstract) | Modifiers.Final, MemberFlags.None) { this.m = m; }
internal static void SetImpl(MethodWrapper mw, MethodInfo impl) { DefaultInterfaceMethodWrapper dimw = mw as DefaultInterfaceMethodWrapper; if (dimw != null) { dimw.impl = impl; } else { ((GhostMethodWrapper)mw).SetDefaultImpl(impl); } }
internal static MethodInfo GetImpl(MethodWrapper mw) { DefaultInterfaceMethodWrapper dimw = mw as DefaultInterfaceMethodWrapper; if (dimw != null) { return dimw.impl; } else { return ((GhostMethodWrapper)mw).GetDefaultImpl(); } }
protected virtual MirandaMethodWrapper AddConflictError(MethodWrapper mw) { return new ErrorMirandaMethodWrapper(DeclaringType, ifmethod, "Conflicting default methods:") .AddConflictError(ifmethod) .AddConflictError(mw); }
private void AddParameterMetadata(MethodBuilder method, MethodWrapper mw) { ParameterBuilder[] pbs; if((mw.DeclaringType.IsPublic && (mw.IsPublic || mw.IsProtected)) || classLoader.EmitDebugInfo) { string[] parameterNames = new string[mw.GetParameters().Length]; GetParameterNamesFromXml(mw.Name, mw.Signature, parameterNames); GetParameterNamesFromSig(mw.Signature, parameterNames); pbs = GetParameterBuilders(method, parameterNames.Length, parameterNames); } else { pbs = GetParameterBuilders(method, mw.GetParameters().Length, null); } if((mw.Modifiers & Modifiers.VarArgs) != 0 && pbs.Length > 0) { AttributeHelper.SetParamArrayAttribute(pbs[pbs.Length - 1]); } AddXmlMapParameterAttributes(method, Name, mw.Name, mw.Signature, ref pbs); }
internal ConstructorForwarder(TypeWrapperFactory context, TypeBuilder typeBuilder, MethodWrapper ctor) : base(ctor.DeclaringType, ctor.Name, ctor.Signature, null, null, null, ctor.Modifiers, MemberFlags.None) { this.context = context; this.typeBuilder = typeBuilder; this.ctor = ctor; }
internal override MethodParametersEntry[] GetMethodParameters(MethodWrapper mw) { MethodBase mb = mw.GetMethod(); if (mb == null) { return null; } ParameterInfo[] parameters = mb.GetParameters(); if (parameters.Length == 0) { return null; } MethodParametersEntry[] mp = new MethodParametersEntry[parameters.Length]; bool hasName = false; for (int i = 0; i < mp.Length; i++) { string name = parameters[i].Name; bool empty = String.IsNullOrEmpty(name); if (empty) { name = "arg" + i; } mp[i].name = name; hasName |= !empty; } if (!hasName) { return null; } return mp; }
internal override MethodWrapper[] GetReplacedMethodsFor(MethodWrapper mw) { IKVM.Internal.MapXml.ReplaceMethodCall[] replacedMethods = ((CompilerClassLoader)GetClassLoader()).GetReplacedMethodsFor(mw); MethodWrapper[] baseReplacedMethodWrappers = base.GetReplacedMethodsFor(mw); if (replacedMethods != null || baseReplacedMethodWrappers != null || this.replacedMethods != null) { List<MethodWrapper> list = new List<MethodWrapper>(); if (replacedMethods != null) { for (int i = 0; i < replacedMethods.Length; i++) { list.Add(new ReplacedMethodWrapper(GetClassLoader().LoadClassByDottedName(replacedMethods[i].Class), replacedMethods[i].Name, replacedMethods[i].Sig, replacedMethods[i].code)); } } if (baseReplacedMethodWrappers != null) { list.AddRange(baseReplacedMethodWrappers); } if (this.replacedMethods != null) { list.AddRange(this.replacedMethods); } return list.ToArray(); } return null; }
internal override object[] GetMethodAnnotations(MethodWrapper mw) { MethodBase mb = mw.GetMethod(); if (mb == null) { return null; } return mb.GetCustomAttributes(false); }
protected override MethodBuilder DefineGhostMethod(string name, MethodAttributes attribs, MethodWrapper mw) { if(typeBuilderGhostInterface != null) { return mw.GetDefineMethodHelper().DefineMethod(this, typeBuilderGhostInterface, name, attribs); } return null; }
internal override object[][] GetParameterAnnotations(MethodWrapper mw) { MethodBase mb = mw.GetMethod(); if (mb == null) { return null; } ParameterInfo[] parameters = mb.GetParameters(); object[][] attribs = new object[parameters.Length][]; for (int i = 0; i < parameters.Length; i++) { attribs[i] = parameters[i].GetCustomAttributes(false); } return attribs; }
protected override void FinishGhost(TypeBuilder typeBuilder, MethodWrapper[] methods) { if(typeBuilderGhostInterface != null) { // TODO consider adding methods from base interface and java.lang.Object as well for(int i = 0; i < methods.Length; i++) { // skip <clinit> if(!methods[i].IsStatic) { TypeWrapper[] args = methods[i].GetParameters(); MethodBuilder stub = methods[i].GetDefineMethodHelper().DefineMethod(this, typeBuilder, methods[i].Name, MethodAttributes.Public); AddParameterMetadata(stub, methods[i]); AttributeHelper.SetModifiers(stub, methods[i].Modifiers, methods[i].IsInternal); CodeEmitter ilgen = CodeEmitter.Create(stub); CodeEmitterLabel end = ilgen.DefineLabel(); TypeWrapper[] implementers = classLoader.GetGhostImplementers(this); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldfld, ghostRefField); ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Isinst, typeBuilderGhostInterface); CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.EmitBrfalse(label); ilgen.Emit(OpCodes.Castclass, typeBuilderGhostInterface); for(int k = 0; k < args.Length; k++) { ilgen.EmitLdarg(k + 1); } ilgen.Emit(OpCodes.Callvirt, (MethodInfo)methods[i].GetMethod()); ilgen.EmitBr(end); ilgen.MarkLabel(label); for(int j = 0; j < implementers.Length; j++) { ilgen.Emit(OpCodes.Dup); ilgen.Emit(OpCodes.Isinst, implementers[j].TypeAsTBD); label = ilgen.DefineLabel(); ilgen.EmitBrfalse(label); ilgen.Emit(OpCodes.Castclass, implementers[j].TypeAsTBD); for(int k = 0; k < args.Length; k++) { ilgen.EmitLdarg(k + 1); } MethodWrapper mw = implementers[j].GetMethodWrapper(methods[i].Name, methods[i].Signature, true); mw.EmitCallvirt(ilgen); ilgen.EmitBr(end); ilgen.MarkLabel(label); } // we need to do a null check (null fails all the isinst checks) ilgen.EmitNullCheck(); ilgen.EmitThrow("java.lang.IncompatibleClassChangeError", Name); ilgen.MarkLabel(end); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); } } // HACK create a scope to enable reuse of "implementers" name if(true) { MethodBuilder mb; CodeEmitter ilgen; CodeEmitterLocal local; // add implicit conversions for all the ghost implementers TypeWrapper[] implementers = classLoader.GetGhostImplementers(this); for(int i = 0; i < implementers.Length; i++) { mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, TypeAsSignatureType, new Type[] { implementers[i].TypeAsSignatureType }); AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); local = ilgen.DeclareLocal(TypeAsSignatureType); ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Stfld, ghostRefField); ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); } // Implement the "IsInstance" method mb = ghostIsInstanceMethod; AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); CodeEmitterLabel end = ilgen.DefineLabel(); for(int i = 0; i < implementers.Length; i++) { ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Isinst, implementers[i].TypeAsTBD); CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.EmitBrfalse(label); ilgen.Emit(OpCodes.Ldc_I4_1); ilgen.EmitBr(end); ilgen.MarkLabel(label); } ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Isinst, typeBuilderGhostInterface); ilgen.Emit(OpCodes.Ldnull); ilgen.Emit(OpCodes.Cgt_Un); ilgen.MarkLabel(end); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // Implement the "IsInstanceArray" method mb = ghostIsInstanceArrayMethod; AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); CodeEmitterLocal localType = ilgen.DeclareLocal(Types.Type); CodeEmitterLocal localRank = ilgen.DeclareLocal(Types.Int32); ilgen.Emit(OpCodes.Ldarg_0); CodeEmitterLabel skip = ilgen.DefineLabel(); ilgen.EmitBrtrue(skip); ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Ret); ilgen.MarkLabel(skip); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Call, Compiler.getTypeMethod); ilgen.Emit(OpCodes.Stloc, localType); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Stloc, localRank); skip = ilgen.DefineLabel(); ilgen.EmitBr(skip); CodeEmitterLabel iter = ilgen.DefineLabel(); ilgen.MarkLabel(iter); ilgen.Emit(OpCodes.Ldloc, localType); ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("GetElementType")); ilgen.Emit(OpCodes.Stloc, localType); ilgen.Emit(OpCodes.Ldloc, localRank); ilgen.Emit(OpCodes.Ldc_I4_1); ilgen.Emit(OpCodes.Sub); ilgen.Emit(OpCodes.Stloc, localRank); ilgen.Emit(OpCodes.Ldloc, localRank); CodeEmitterLabel typecheck = ilgen.DefineLabel(); ilgen.EmitBrfalse(typecheck); ilgen.MarkLabel(skip); ilgen.Emit(OpCodes.Ldloc, localType); ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("get_IsArray")); ilgen.EmitBrtrue(iter); ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Ret); ilgen.MarkLabel(typecheck); for(int i = 0; i < implementers.Length; i++) { ilgen.Emit(OpCodes.Ldtoken, implementers[i].TypeAsTBD); ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle")); ilgen.Emit(OpCodes.Ldloc, localType); ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("IsAssignableFrom")); CodeEmitterLabel label = ilgen.DefineLabel(); ilgen.EmitBrfalse(label); ilgen.Emit(OpCodes.Ldc_I4_1); ilgen.Emit(OpCodes.Ret); ilgen.MarkLabel(label); } ilgen.Emit(OpCodes.Ldtoken, typeBuilderGhostInterface); ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle")); ilgen.Emit(OpCodes.Ldloc, localType); ilgen.Emit(OpCodes.Callvirt, Types.Type.GetMethod("IsAssignableFrom")); skip = ilgen.DefineLabel(); ilgen.EmitBrfalse(skip); ilgen.Emit(OpCodes.Ldc_I4_1); ilgen.Emit(OpCodes.Ret); ilgen.MarkLabel(skip); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldtoken, typeBuilder); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Call, StaticCompiler.GetRuntimeType("IKVM.Runtime.GhostTag").GetMethod("IsGhostArrayInstance", BindingFlags.NonPublic | BindingFlags.Static)); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // Implement the "Cast" method mb = ghostCastMethod; AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); end = ilgen.DefineLabel(); for(int i = 0; i < implementers.Length; i++) { ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Isinst, implementers[i].TypeAsTBD); ilgen.EmitBrtrue(end); } ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Castclass, typeBuilderGhostInterface); ilgen.Emit(OpCodes.Pop); ilgen.MarkLabel(end); local = ilgen.DeclareLocal(TypeAsSignatureType); ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Stfld, ghostRefField); ilgen.Emit(OpCodes.Ldloca, local); ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // Add "ToObject" methods mb = typeBuilder.DefineMethod("ToObject", MethodAttributes.HideBySig | MethodAttributes.Public, Types.Object, Type.EmptyTypes); AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldfld, ghostRefField); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // Implement the "CastArray" method // NOTE unlike "Cast" this doesn't return anything, it just throws a ClassCastException if the // cast is unsuccessful. Also, because of the complexity of this test, we call IsInstanceArray // instead of reimplementing the check here. mb = ghostCastArrayMethod; AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); end = ilgen.DefineLabel(); ilgen.Emit(OpCodes.Ldarg_0); ilgen.EmitBrfalse(end); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Call, ghostIsInstanceArrayMethod); ilgen.EmitBrtrue(end); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldtoken, typeBuilder); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Call, StaticCompiler.GetRuntimeType("IKVM.Runtime.GhostTag").GetMethod("ThrowClassCastException", BindingFlags.NonPublic | BindingFlags.Static)); ilgen.MarkLabel(end); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // Implement the "Equals" method mb = typeBuilder.DefineMethod("Equals", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual, Types.Boolean, new Type[] { Types.Object }); AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldfld, ghostRefField); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ceq); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // Implement the "GetHashCode" method mb = typeBuilder.DefineMethod("GetHashCode", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Virtual, Types.Int32, Type.EmptyTypes); AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldfld, ghostRefField); ilgen.Emit(OpCodes.Callvirt, Types.Object.GetMethod("GetHashCode")); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // Implement the "op_Equality" method mb = typeBuilder.DefineMethod("op_Equality", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, Types.Boolean, new Type[] { typeBuilder, typeBuilder }); AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); ilgen.EmitLdarga(0); ilgen.Emit(OpCodes.Ldfld, ghostRefField); ilgen.EmitLdarga(1); ilgen.Emit(OpCodes.Ldfld, ghostRefField); ilgen.Emit(OpCodes.Ceq); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); // Implement the "op_Inequality" method mb = typeBuilder.DefineMethod("op_Inequality", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, Types.Boolean, new Type[] { typeBuilder, typeBuilder }); AttributeHelper.HideFromJava(mb); ilgen = CodeEmitter.Create(mb); ilgen.EmitLdarga(0); ilgen.Emit(OpCodes.Ldfld, ghostRefField); ilgen.EmitLdarga(1); ilgen.Emit(OpCodes.Ldfld, ghostRefField); ilgen.Emit(OpCodes.Ceq); ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Ceq); ilgen.Emit(OpCodes.Ret); ilgen.DoEmit(); } } }
internal override MethodParametersEntry[] GetMethodParameters(MethodWrapper mw) { return DeclaringTypeWrapper.GetMethodParameters(DeclaringTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, false)); }
internal override MethodBase LinkMethod(MethodWrapper mw) { return ((RemappedMethodBaseWrapper)mw).DoLink(); }
private static void AddMethodIfUnique(List<MethodWrapper> methods, MethodWrapper method) { foreach (MethodWrapper mw in methods) { if (mw.Name == method.Name && mw.Signature == method.Signature) { // ignore duplicate return; } } methods.Add(method); }
private static object InvokeNonVirtual(ManagedJNIEnv env, MethodWrapper mw, object obj, object[] argarray) { if (mw.HasCallerID || mw.IsDynamicOnly) { throw new NotSupportedException(); } if (mw.DeclaringType.IsRemapped && !mw.DeclaringType.TypeAsBaseType.IsInstanceOfType(obj)) { return mw.InvokeNonvirtualRemapped(obj, argarray); } else { Delegate del = (Delegate)Activator.CreateInstance(mw.GetDelegateType(), new object[] { obj, mw.GetMethod().MethodHandle.GetFunctionPointer() }); try { return del.DynamicInvoke(argarray); } catch (TargetInvocationException x) { throw ikvm.runtime.Util.mapException(x.InnerException); } } }
internal override object GetAnnotationDefault(MethodWrapper mw) { if (mw.IsOptionalAttributeAnnotationValue) { if (mw.ReturnType == PrimitiveTypeWrapper.BOOLEAN) { return java.lang.Boolean.FALSE; } else if (mw.ReturnType == PrimitiveTypeWrapper.BYTE) { return java.lang.Byte.valueOf((byte)0); } else if (mw.ReturnType == PrimitiveTypeWrapper.CHAR) { return java.lang.Character.valueOf((char)0); } else if (mw.ReturnType == PrimitiveTypeWrapper.SHORT) { return java.lang.Short.valueOf((short)0); } else if (mw.ReturnType == PrimitiveTypeWrapper.INT) { return java.lang.Integer.valueOf(0); } else if (mw.ReturnType == PrimitiveTypeWrapper.FLOAT) { return java.lang.Float.valueOf(0F); } else if (mw.ReturnType == PrimitiveTypeWrapper.LONG) { return java.lang.Long.valueOf(0L); } else if (mw.ReturnType == PrimitiveTypeWrapper.DOUBLE) { return java.lang.Double.valueOf(0D); } else if (mw.ReturnType == CoreClasses.java.lang.String.Wrapper) { return ""; } else if (mw.ReturnType == CoreClasses.java.lang.Class.Wrapper) { return (java.lang.Class)typeof(ikvm.@internal.__unspecified); } else if (mw.ReturnType is EnumEnumTypeWrapper) { EnumEnumTypeWrapper eetw = (EnumEnumTypeWrapper)mw.ReturnType; return eetw.GetUnspecifiedValue(); } else if (mw.ReturnType.IsArray) { return Array.CreateInstance(mw.ReturnType.TypeAsArrayType, 0); } } return null; }
internal InvokeArgsProcessor(MethodWrapper mw, MethodBase method, object original_obj, object[] original_args, [email protected] callerID) { TypeWrapper[] argTypes = mw.GetParameters(); if(!mw.IsStatic && method.IsStatic && mw.Name != "<init>") { // we've been redirected to a static method, so we have to copy the 'obj' into the args object[] nargs = new object[original_args.Length + 1]; nargs[0] = original_obj; original_args.CopyTo(nargs, 1); this.obj = null; this.args = nargs; for(int i = 0; i < argTypes.Length; i++) { if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost) { object v = Activator.CreateInstance(argTypes[i].TypeAsSignatureType); argTypes[i].GhostRefField.SetValue(v, args[i + 1]); args[i + 1] = v; } } } else { this.obj = original_obj; this.args = original_args; for(int i = 0; i < argTypes.Length; i++) { if(!argTypes[i].IsUnloadable && argTypes[i].IsGhost) { if(this.args == original_args) { this.args = (object[])args.Clone(); } object v = Activator.CreateInstance(argTypes[i].TypeAsSignatureType); argTypes[i].GhostRefField.SetValue(v, args[i]); this.args[i] = v; } } } if(mw.HasCallerID) { object[] nargs = new object[args.Length + 1]; Array.Copy(args, nargs, args.Length); nargs[args.Length] = callerID; args = nargs; } }
private static ConstructorInfo AddConstructor(TypeBuilder tb, MethodWrapper defaultConstructor, ConstructorInfo serializationConstructor, bool callReadObject) { ConstructorBuilder ctor = tb.DefineConstructor(MethodAttributes.Family, CallingConventions.Standard, new Type[] { JVM.Import(typeof(SerializationInfo)), JVM.Import(typeof(StreamingContext)) }); AttributeHelper.HideFromJava(ctor); ctor.AddDeclarativeSecurity(SecurityAction.Demand, psetSerializationFormatter); CodeEmitter ilgen = CodeEmitter.Create(ctor); ilgen.Emit(OpCodes.Ldarg_0); if (defaultConstructor != null) { defaultConstructor.EmitCall(ilgen); } else { ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldarg_2); ilgen.Emit(OpCodes.Call, serializationConstructor); } if (callReadObject) { ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); TypeWrapper serializationHelper = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.Serialization"); MethodWrapper mw = serializationHelper.GetMethodWrapper("readObject", "(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V", false); mw.Link(); mw.EmitCall(ilgen); } ilgen.Emit(OpCodes.Ret); return ctor; }