ikvm-fork/runtime/TypeWrapper.cs

12321 строка
372 KiB
C#
Исходник Обычный вид История

2002-12-18 19:00:25 +03:00
/*
Copyright (C) 2002-2008 Jeroen Frijters
2002-12-18 19:00:25 +03:00
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
using System;
using System.Collections;
2005-12-07 12:06:32 +03:00
using System.Collections.Generic;
2002-12-18 19:00:25 +03:00
using System.Reflection;
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2002-12-18 19:00:25 +03:00
using System.Reflection.Emit;
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
using System.Diagnostics;
2005-05-23 12:24:07 +04:00
using System.Security;
using System.Security.Permissions;
2004-09-09 15:17:55 +04:00
using IKVM.Attributes;
2002-12-18 19:00:25 +03:00
2004-10-19 17:43:55 +04:00
2005-06-01 13:49:30 +04:00
namespace IKVM.Internal
2003-05-13 00:00:15 +04:00
{
2006-04-05 12:18:58 +04:00
struct ExModifiers
{
internal readonly Modifiers Modifiers;
internal readonly bool IsInternal;
internal ExModifiers(Modifiers modifiers, bool isInternal)
{
this.Modifiers = modifiers;
this.IsInternal = isInternal;
}
}
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2008-06-03 11:13:49 +04:00
static class EmitHelper
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
private static MethodInfo objectToString = typeof(object).GetMethod("ToString", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
2006-04-11 16:05:24 +04:00
private static MethodInfo verboseCastFailure = JVM.SafeGetEnvironmentVariable("IKVM_VERBOSE_CAST") == null ? null : ByteCodeHelperMethods.VerboseCastFailure;
2005-12-07 12:06:32 +03:00
internal static void Throw(CodeEmitter ilgen, string dottedClassName)
2005-06-01 13:49:30 +04:00
{
TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName);
MethodWrapper mw = exception.GetMethodWrapper("<init>", "()V", false);
mw.Link();
mw.EmitNewobj(ilgen);
ilgen.Emit(OpCodes.Throw);
}
2003-05-30 16:08:59 +04:00
internal static void Throw(CodeEmitter ilgen, string dottedClassName, string message)
2005-06-01 13:49:30 +04:00
{
TypeWrapper exception = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(dottedClassName);
ilgen.Emit(OpCodes.Ldstr, message);
MethodWrapper mw = exception.GetMethodWrapper("<init>", "(Ljava.lang.String;)V", false);
mw.Link();
mw.EmitNewobj(ilgen);
ilgen.Emit(OpCodes.Throw);
}
internal static void NullCheck(CodeEmitter ilgen)
2005-06-01 13:49:30 +04:00
{
// I think this is the most efficient way to generate a NullReferenceException if the
// reference is null
ilgen.Emit(OpCodes.Ldvirtftn, objectToString);
2003-11-17 15:01:50 +03:00
ilgen.Emit(OpCodes.Pop);
}
2004-03-08 18:18:47 +03:00
internal static void Castclass(CodeEmitter ilgen, Type type)
2005-06-01 13:49:30 +04:00
{
if(verboseCastFailure != null)
{
LocalBuilder lb = ilgen.DeclareLocal(typeof(object));
ilgen.Emit(OpCodes.Stloc, lb);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Isinst, type);
ilgen.Emit(OpCodes.Dup);
CodeEmitterLabel ok = ilgen.DefineLabel();
2005-06-01 13:49:30 +04:00
ilgen.Emit(OpCodes.Brtrue_S, ok);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Brfalse_S, ok); // handle null
ilgen.Emit(OpCodes.Ldtoken, type);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Call, verboseCastFailure);
ilgen.MarkLabel(ok);
}
else
{
ilgen.Emit(OpCodes.Castclass, type);
}
}
2005-02-11 17:46:58 +03:00
2005-06-01 13:49:30 +04:00
// This is basically the same as Castclass, except that it
// throws an IncompatibleClassChangeError on failure.
internal static void EmitAssertType(CodeEmitter ilgen, Type type)
2005-02-11 17:46:58 +03:00
{
LocalBuilder lb = ilgen.DeclareLocal(typeof(object));
ilgen.Emit(OpCodes.Stloc, lb);
ilgen.Emit(OpCodes.Ldloc, lb);
ilgen.Emit(OpCodes.Isinst, type);
ilgen.Emit(OpCodes.Dup);
CodeEmitterLabel ok = ilgen.DefineLabel();
2005-02-16 14:20:43 +03:00
ilgen.Emit(OpCodes.Brtrue_S, ok);
2005-02-11 17:46:58 +03:00
ilgen.Emit(OpCodes.Ldloc, lb);
2005-02-16 14:20:43 +03:00
ilgen.Emit(OpCodes.Brfalse_S, ok); // handle null
2005-06-01 13:49:30 +04:00
EmitHelper.Throw(ilgen, "java.lang.IncompatibleClassChangeError");
2005-02-11 17:46:58 +03:00
ilgen.MarkLabel(ok);
}
}
2005-12-07 12:06:32 +03:00
#endif
2008-06-03 11:13:49 +04:00
static class AttributeHelper
2005-02-16 14:20:43 +03:00
{
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
private static CustomAttributeBuilder hideFromJavaAttribute;
2006-04-11 18:59:43 +04:00
#if STATIC_COMPILER
2006-05-04 12:09:56 +04:00
private static CustomAttributeBuilder ghostInterfaceAttribute;
private static CustomAttributeBuilder deprecatedAttribute;
2005-06-01 13:49:30 +04:00
private static CustomAttributeBuilder editorBrowsableNever;
private static ConstructorInfo implementsAttribute;
private static ConstructorInfo throwsAttribute;
private static ConstructorInfo sourceFileAttribute;
2005-08-22 16:42:02 +04:00
private static ConstructorInfo lineNumberTableAttribute1;
private static ConstructorInfo lineNumberTableAttribute2;
2005-10-01 15:16:11 +04:00
private static ConstructorInfo enclosingMethodAttribute;
private static ConstructorInfo signatureAttribute;
private static CustomAttributeBuilder paramArrayAttribute;
private static ConstructorInfo nonNestedInnerClassAttribute;
private static ConstructorInfo nonNestedOuterClassAttribute;
private static Type typeofModifiers = JVM.LoadType(typeof(Modifiers));
private static Type typeofSourceFileAttribute = JVM.LoadType(typeof(SourceFileAttribute));
private static Type typeofLineNumberTableAttribute = JVM.LoadType(typeof(LineNumberTableAttribute));
private static Type typeofEnclosingMethodAttribute = JVM.LoadType(typeof(EnclosingMethodAttribute));
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
#endif // !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
private static Type typeofRemappedClassAttribute = JVM.LoadType(typeof(RemappedClassAttribute));
private static Type typeofRemappedTypeAttribute = JVM.LoadType(typeof(RemappedTypeAttribute));
private static Type typeofModifiersAttribute = JVM.LoadType(typeof(ModifiersAttribute));
private static Type typeofRemappedInterfaceMethodAttribute = JVM.LoadType(typeof(RemappedInterfaceMethodAttribute));
private static Type typeofNameSigAttribute = JVM.LoadType(typeof(NameSigAttribute));
private static Type typeofJavaModuleAttribute = JVM.LoadType(typeof(JavaModuleAttribute));
private static Type typeofSignatureAttribute = JVM.LoadType(typeof(SignatureAttribute));
private static Type typeofInnerClassAttribute = JVM.LoadType(typeof(InnerClassAttribute));
private static Type typeofImplementsAttribute = JVM.LoadType(typeof(ImplementsAttribute));
private static Type typeofGhostInterfaceAttribute = JVM.LoadType(typeof(GhostInterfaceAttribute));
private static Type typeofExceptionIsUnsafeForMappingAttribute = JVM.LoadType(typeof(ExceptionIsUnsafeForMappingAttribute));
private static Type typeofThrowsAttribute = JVM.LoadType(typeof(ThrowsAttribute));
private static Type typeofHideFromReflectionAttribute = JVM.LoadType(typeof(HideFromReflectionAttribute));
private static Type typeofHideFromJavaAttribute = JVM.LoadType(typeof(HideFromJavaAttribute));
private static Type typeofNoPackagePrefixAttribute = JVM.LoadType(typeof(NoPackagePrefixAttribute));
private static Type typeofConstantValueAttribute = JVM.LoadType(typeof(ConstantValueAttribute));
private static Type typeofAnnotationAttributeAttribute = JVM.LoadType(typeof(AnnotationAttributeAttribute));
private static Type typeofNonNestedInnerClassAttribute = JVM.LoadType(typeof(NonNestedInnerClassAttribute));
private static Type typeofNonNestedOuterClassAttribute = JVM.LoadType(typeof(NonNestedOuterClassAttribute));
2005-12-07 12:06:32 +03:00
2006-10-01 12:09:25 +04:00
#if STATIC_COMPILER && !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
private static object ParseValue(TypeWrapper tw, string val)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if(tw == CoreClasses.java.lang.String.Wrapper)
{
return val;
}
else if(tw.TypeAsTBD.IsEnum)
{
2005-12-07 12:06:32 +03:00
if(tw.TypeAsTBD.Assembly.ReflectionOnly)
{
// TODO implement full parsing semantics
FieldInfo field = tw.TypeAsTBD.GetField(val);
if(field == null)
{
throw new NotImplementedException("Parsing enum value: " + val);
}
return field.GetRawConstantValue();
}
2005-06-01 13:49:30 +04:00
return Enum.Parse(tw.TypeAsTBD, val);
}
else if(tw.TypeAsTBD == typeof(Type))
{
2006-10-01 12:09:25 +04:00
TypeWrapper valtw = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast(val);
if(valtw != null)
{
return valtw.TypeAsBaseType;
}
2005-06-01 13:49:30 +04:00
return Type.GetType(val, true);
}
else if(tw == PrimitiveTypeWrapper.BOOLEAN)
{
return bool.Parse(val);
}
else if(tw == PrimitiveTypeWrapper.BYTE)
{
return (byte)sbyte.Parse(val);
}
else if(tw == PrimitiveTypeWrapper.CHAR)
{
return char.Parse(val);
}
else if(tw == PrimitiveTypeWrapper.SHORT)
{
return short.Parse(val);
}
else if(tw == PrimitiveTypeWrapper.INT)
{
return int.Parse(val);
}
else if(tw == PrimitiveTypeWrapper.FLOAT)
{
return float.Parse(val);
}
else if(tw == PrimitiveTypeWrapper.LONG)
{
return long.Parse(val);
}
else if(tw == PrimitiveTypeWrapper.DOUBLE)
{
return double.Parse(val);
}
else
{
throw new NotImplementedException();
}
2005-04-27 10:10:01 +04:00
}
2006-10-01 12:09:25 +04:00
2005-06-01 13:49:30 +04:00
private static void SetPropertiesAndFields(Attribute attrib, IKVM.Internal.MapXml.Attribute attr)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
Type t = attrib.GetType();
if(attr.Properties != null)
{
foreach(IKVM.Internal.MapXml.Param prop in attr.Properties)
{
PropertyInfo pi = t.GetProperty(prop.Name);
pi.SetValue(attrib, ParseValue(ClassFile.FieldTypeWrapperFromSig(ClassLoaderWrapper.GetBootstrapClassLoader(), new Hashtable(), prop.Sig), prop.Value), null);
}
}
if(attr.Fields != null)
{
foreach(IKVM.Internal.MapXml.Param field in attr.Fields)
{
FieldInfo fi = t.GetField(field.Name);
fi.SetValue(attrib, ParseValue(ClassFile.FieldTypeWrapperFromSig(ClassLoaderWrapper.GetBootstrapClassLoader(), new Hashtable(), field.Sig), field.Value));
}
}
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static Attribute InstantiatePseudoCustomAttribute(IKVM.Internal.MapXml.Attribute attr)
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler.GetType(attr.Type);
2005-06-01 13:49:30 +04:00
Type[] argTypes;
object[] args;
GetAttributeArgsAndTypes(attr, out argTypes, out args);
ConstructorInfo ci = t.GetConstructor(argTypes);
Attribute attrib = ci.Invoke(args) as Attribute;
SetPropertiesAndFields(attrib, attr);
return attrib;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
private static bool IsCodeAccessSecurityAttribute(IKVM.Internal.MapXml.Attribute attr, out SecurityAction action, out PermissionSet pset)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
action = SecurityAction.Deny;
pset = null;
if(attr.Type != null)
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler.GetType(attr.Type);
2005-06-01 13:49:30 +04:00
if(typeof(CodeAccessSecurityAttribute).IsAssignableFrom(t))
{
Type[] argTypes;
object[] args;
GetAttributeArgsAndTypes(attr, out argTypes, out args);
ConstructorInfo ci = t.GetConstructor(argTypes);
CodeAccessSecurityAttribute attrib = ci.Invoke(args) as CodeAccessSecurityAttribute;
SetPropertiesAndFields(attrib, attr);
action = attrib.Action;
pset = new PermissionSet(PermissionState.None);
pset.AddPermission(attrib.CreatePermission());
return true;
}
}
return false;
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute(TypeBuilder tb, IKVM.Internal.MapXml.Attribute attr)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action;
PermissionSet pset;
if(IsCodeAccessSecurityAttribute(attr, out action, out pset))
{
tb.AddDeclarativeSecurity(action, pset);
}
else
{
tb.SetCustomAttribute(CreateCustomAttribute(attr));
}
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute(FieldBuilder fb, IKVM.Internal.MapXml.Attribute attr)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
fb.SetCustomAttribute(CreateCustomAttribute(attr));
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute(ParameterBuilder pb, IKVM.Internal.MapXml.Attribute attr)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
pb.SetCustomAttribute(CreateCustomAttribute(attr));
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute(MethodBuilder mb, IKVM.Internal.MapXml.Attribute attr)
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action;
PermissionSet pset;
if(IsCodeAccessSecurityAttribute(attr, out action, out pset))
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
mb.AddDeclarativeSecurity(action, pset);
2005-05-27 16:44:06 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-05-27 16:44:06 +04:00
{
2005-06-01 13:49:30 +04:00
mb.SetCustomAttribute(CreateCustomAttribute(attr));
2005-05-27 16:44:06 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute(ConstructorBuilder cb, IKVM.Internal.MapXml.Attribute attr)
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
SecurityAction action;
PermissionSet pset;
if(IsCodeAccessSecurityAttribute(attr, out action, out pset))
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
cb.AddDeclarativeSecurity(action, pset);
}
else
{
cb.SetCustomAttribute(CreateCustomAttribute(attr));
2005-05-23 12:24:07 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute(PropertyBuilder pb, IKVM.Internal.MapXml.Attribute attr)
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
pb.SetCustomAttribute(CreateCustomAttribute(attr));
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetCustomAttribute(AssemblyBuilder ab, IKVM.Internal.MapXml.Attribute attr)
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
ab.SetCustomAttribute(CreateCustomAttribute(attr));
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
private static void GetAttributeArgsAndTypes(IKVM.Internal.MapXml.Attribute attr, out Type[] argTypes, out object[] args)
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO add error handling
TypeWrapper[] twargs = ClassFile.ArgTypeWrapperListFromSig(ClassLoaderWrapper.GetBootstrapClassLoader(), new Hashtable(), attr.Sig);
argTypes = new Type[twargs.Length];
args = new object[argTypes.Length];
for(int i = 0; i < twargs.Length; i++)
{
argTypes[i] = twargs[i].TypeAsSignatureType;
TypeWrapper tw = twargs[i];
if(tw == CoreClasses.java.lang.Object.Wrapper)
{
tw = ClassFile.FieldTypeWrapperFromSig(ClassLoaderWrapper.GetBootstrapClassLoader(), new Hashtable(), attr.Params[i].Sig);
}
if(tw.IsArray)
{
Array arr = Array.CreateInstance(tw.ElementTypeWrapper.TypeAsArrayType, attr.Params[i].Elements.Length);
for(int j = 0; j < arr.Length; j++)
{
arr.SetValue(ParseValue(tw.ElementTypeWrapper, attr.Params[i].Elements[j].Value), j);
}
args[i] = arr;
}
else
{
args[i] = ParseValue(tw, attr.Params[i].Value);
}
}
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
private static CustomAttributeBuilder CreateCustomAttribute(IKVM.Internal.MapXml.Attribute attr)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO add error handling
Type[] argTypes;
object[] args;
GetAttributeArgsAndTypes(attr, out argTypes, out args);
if(attr.Type != null)
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
Type t = StaticCompiler.GetType(attr.Type);
2005-06-01 13:49:30 +04:00
if(typeof(CodeAccessSecurityAttribute).IsAssignableFrom(t))
{
throw new NotImplementedException("CodeAccessSecurityAttribute support not implemented");
}
ConstructorInfo ci = t.GetConstructor(argTypes);
2005-12-07 12:06:32 +03:00
if(ci == null)
{
throw new InvalidOperationException(string.Format("Constructor missing: {0}::<init>{1}", attr.Class, attr.Sig));
}
2005-06-01 13:49:30 +04:00
PropertyInfo[] namedProperties;
object[] propertyValues;
if(attr.Properties != null)
{
namedProperties = new PropertyInfo[attr.Properties.Length];
propertyValues = new object[attr.Properties.Length];
for(int i = 0; i < namedProperties.Length; i++)
{
namedProperties[i] = t.GetProperty(attr.Properties[i].Name);
propertyValues[i] = ParseValue(ClassFile.FieldTypeWrapperFromSig(ClassLoaderWrapper.GetBootstrapClassLoader(), new Hashtable(), attr.Properties[i].Sig), attr.Properties[i].Value);
}
}
else
{
namedProperties = new PropertyInfo[0];
propertyValues = new object[0];
}
FieldInfo[] namedFields;
object[] fieldValues;
if(attr.Fields != null)
{
namedFields = new FieldInfo[attr.Fields.Length];
fieldValues = new object[attr.Fields.Length];
for(int i = 0; i < namedFields.Length; i++)
{
namedFields[i] = t.GetField(attr.Fields[i].Name);
fieldValues[i] = ParseValue(ClassFile.FieldTypeWrapperFromSig(ClassLoaderWrapper.GetBootstrapClassLoader(), new Hashtable(), attr.Fields[i].Sig), attr.Fields[i].Value);
}
}
else
{
namedFields = new FieldInfo[0];
fieldValues = new object[0];
}
return new CustomAttributeBuilder(ci, args, namedProperties, propertyValues, namedFields, fieldValues);
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if(attr.Properties != null)
{
throw new NotImplementedException("Setting property values on Java attributes is not implemented");
}
TypeWrapper t = ClassLoaderWrapper.LoadClassCritical(attr.Class);
MethodWrapper mw = t.GetMethodWrapper("<init>", attr.Sig, false);
mw.Link();
ConstructorInfo ci = (ConstructorInfo)mw.GetMethod();
2005-12-07 12:06:32 +03:00
if(ci == null)
{
throw new InvalidOperationException(string.Format("Constructor missing: {0}::<init>{1}", attr.Class, attr.Sig));
}
2005-06-01 13:49:30 +04:00
FieldInfo[] namedFields;
object[] fieldValues;
if(attr.Fields != null)
{
namedFields = new FieldInfo[attr.Fields.Length];
fieldValues = new object[attr.Fields.Length];
for(int i = 0; i < namedFields.Length; i++)
{
FieldWrapper fw = t.GetFieldWrapper(attr.Fields[i].Name, attr.Fields[i].Sig);
fw.Link();
namedFields[i] = fw.GetField();
fieldValues[i] = ParseValue(ClassFile.FieldTypeWrapperFromSig(ClassLoaderWrapper.GetBootstrapClassLoader(), new Hashtable(), attr.Fields[i].Sig), attr.Fields[i].Value);
}
}
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
namedFields = new FieldInfo[0];
fieldValues = new object[0];
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
return new CustomAttributeBuilder(ci, args, namedFields, fieldValues);
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
}
#endif
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
internal static void SetEditorBrowsableNever(TypeBuilder tb)
{
if(editorBrowsableNever == null)
{
editorBrowsableNever = new CustomAttributeBuilder(StaticCompiler.GetType("System.ComponentModel.EditorBrowsableAttribute").GetConstructor(new Type[] { StaticCompiler.GetType("System.ComponentModel.EditorBrowsableState") }), new object[] { (int)System.ComponentModel.EditorBrowsableState.Never });
}
tb.SetCustomAttribute(editorBrowsableNever);
}
2005-06-01 13:49:30 +04:00
internal static void SetEditorBrowsableNever(MethodBuilder mb)
{
if(editorBrowsableNever == null)
2005-04-27 10:10:01 +04:00
{
2006-04-10 13:09:09 +04:00
editorBrowsableNever = new CustomAttributeBuilder(StaticCompiler.GetType("System.ComponentModel.EditorBrowsableAttribute").GetConstructor(new Type[] { StaticCompiler.GetType("System.ComponentModel.EditorBrowsableState") }), new object[] { (int)System.ComponentModel.EditorBrowsableState.Never });
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
mb.SetCustomAttribute(editorBrowsableNever);
2005-04-27 10:10:01 +04:00
}
2005-05-23 12:24:07 +04:00
2006-12-28 10:46:21 +03:00
internal static void SetEditorBrowsableNever(ConstructorBuilder cb)
{
if(editorBrowsableNever == null)
{
editorBrowsableNever = new CustomAttributeBuilder(StaticCompiler.GetType("System.ComponentModel.EditorBrowsableAttribute").GetConstructor(new Type[] { StaticCompiler.GetType("System.ComponentModel.EditorBrowsableState") }), new object[] { (int)System.ComponentModel.EditorBrowsableState.Never });
}
cb.SetCustomAttribute(editorBrowsableNever);
}
2005-06-01 13:49:30 +04:00
internal static void SetEditorBrowsableNever(PropertyBuilder pb)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if(editorBrowsableNever == null)
2005-05-23 12:24:07 +04:00
{
2006-04-10 13:09:09 +04:00
editorBrowsableNever = new CustomAttributeBuilder(StaticCompiler.GetType("System.ComponentModel.EditorBrowsableAttribute").GetConstructor(new Type[] { StaticCompiler.GetType("System.ComponentModel.EditorBrowsableState") }), new object[] { (int)System.ComponentModel.EditorBrowsableState.Never });
2005-05-23 12:24:07 +04:00
}
2005-06-01 13:49:30 +04:00
pb.SetCustomAttribute(editorBrowsableNever);
}
internal static void SetDeprecatedAttribute(MethodBase mb)
{
if(deprecatedAttribute == null)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder(typeof(ObsoleteAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
MethodBuilder method = mb as MethodBuilder;
if(method != null)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
method.SetCustomAttribute(deprecatedAttribute);
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
else
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
((ConstructorBuilder)mb).SetCustomAttribute(deprecatedAttribute);
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
}
internal static void SetDeprecatedAttribute(TypeBuilder tb)
{
if(deprecatedAttribute == null)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder(typeof(ObsoleteAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
tb.SetCustomAttribute(deprecatedAttribute);
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetDeprecatedAttribute(FieldBuilder fb)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if(deprecatedAttribute == null)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
deprecatedAttribute = new CustomAttributeBuilder(typeof(ObsoleteAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
2005-04-27 10:10:01 +04:00
}
2005-06-01 13:49:30 +04:00
fb.SetCustomAttribute(deprecatedAttribute);
}
2006-10-04 13:03:18 +04:00
internal static void SetDeprecatedAttribute(PropertyBuilder pb)
{
if(deprecatedAttribute == null)
{
deprecatedAttribute = new CustomAttributeBuilder(typeof(ObsoleteAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
}
pb.SetCustomAttribute(deprecatedAttribute);
}
2005-06-01 13:49:30 +04:00
internal static void SetThrowsAttribute(MethodBase mb, string[] exceptions)
{
if(exceptions != null && exceptions.Length != 0)
2005-04-27 10:10:01 +04:00
{
2005-06-01 13:49:30 +04:00
if(throwsAttribute == null)
2005-04-27 10:10:01 +04:00
{
2005-12-07 12:06:32 +03:00
throwsAttribute = typeofThrowsAttribute.GetConstructor(new Type[] { typeof(string[]) });
2005-06-01 13:49:30 +04:00
}
if(mb is MethodBuilder)
{
MethodBuilder method = (MethodBuilder)mb;
method.SetCustomAttribute(new CustomAttributeBuilder(throwsAttribute, new object[] { exceptions }));
}
else
{
ConstructorBuilder constructor = (ConstructorBuilder)mb;
constructor.SetCustomAttribute(new CustomAttributeBuilder(throwsAttribute, new object[] { exceptions }));
2005-04-27 10:10:01 +04:00
}
}
2004-11-23 20:46:39 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void SetGhostInterface(TypeBuilder typeBuilder)
2004-11-23 20:46:39 +03:00
{
2005-06-01 13:49:30 +04:00
if(ghostInterfaceAttribute == null)
{
2005-12-07 12:06:32 +03:00
ghostInterfaceAttribute = new CustomAttributeBuilder(typeofGhostInterfaceAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
2005-06-01 13:49:30 +04:00
}
typeBuilder.SetCustomAttribute(ghostInterfaceAttribute);
2004-11-23 20:46:39 +03:00
}
internal static void SetNonNestedInnerClass(TypeBuilder typeBuilder, string className)
{
if(nonNestedInnerClassAttribute == null)
{
nonNestedInnerClassAttribute = typeofNonNestedInnerClassAttribute.GetConstructor(new Type[] { typeof(string) });
}
typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(nonNestedInnerClassAttribute, new object[] { className }));
}
internal static void SetNonNestedOuterClass(TypeBuilder typeBuilder, string className)
{
if(nonNestedOuterClassAttribute == null)
{
nonNestedOuterClassAttribute = typeofNonNestedOuterClassAttribute.GetConstructor(new Type[] { typeof(string) });
}
typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(nonNestedOuterClassAttribute, new object[] { className }));
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2003-11-17 15:01:50 +03:00
2005-08-14 19:49:50 +04:00
internal static void HideFromReflection(MethodBuilder mb)
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofHideFromReflectionAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
2005-06-01 13:49:30 +04:00
mb.SetCustomAttribute(cab);
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
2005-08-14 19:49:50 +04:00
internal static void HideFromReflection(FieldBuilder fb)
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofHideFromReflectionAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
2005-08-14 19:49:50 +04:00
fb.SetCustomAttribute(cab);
}
internal static void HideFromReflection(PropertyBuilder pb)
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofHideFromReflectionAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
2005-08-14 19:49:50 +04:00
pb.SetCustomAttribute(cab);
}
2006-04-10 13:09:09 +04:00
#endif // !COMPACT_FRAMEWORK
2005-08-14 19:49:50 +04:00
internal static bool IsHideFromReflection(MethodInfo mi)
{
2005-12-07 12:06:32 +03:00
return IsDefined(mi, typeofHideFromReflectionAttribute);
2005-08-14 19:49:50 +04:00
}
internal static bool IsHideFromReflection(FieldInfo fi)
{
2005-12-07 12:06:32 +03:00
return IsDefined(fi, typeofHideFromReflectionAttribute);
2005-08-14 19:49:50 +04:00
}
internal static bool IsHideFromReflection(PropertyInfo pi)
{
2005-12-07 12:06:32 +03:00
return IsDefined(pi, typeofHideFromReflectionAttribute);
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal static void HideFromJava(TypeBuilder typeBuilder)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if(hideFromJavaAttribute == null)
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder(typeofHideFromJavaAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
2005-06-01 13:49:30 +04:00
}
typeBuilder.SetCustomAttribute(hideFromJavaAttribute);
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava(ConstructorBuilder cb)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if(hideFromJavaAttribute == null)
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder(typeofHideFromJavaAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
2005-06-01 13:49:30 +04:00
}
cb.SetCustomAttribute(hideFromJavaAttribute);
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava(MethodBuilder mb)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if(hideFromJavaAttribute == null)
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder(typeofHideFromJavaAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
2005-06-01 13:49:30 +04:00
}
mb.SetCustomAttribute(hideFromJavaAttribute);
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal static void HideFromJava(FieldBuilder fb)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
if(hideFromJavaAttribute == null)
2003-11-17 15:01:50 +03:00
{
2005-12-07 12:06:32 +03:00
hideFromJavaAttribute = new CustomAttributeBuilder(typeofHideFromJavaAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
fb.SetCustomAttribute(hideFromJavaAttribute);
}
2006-09-26 08:53:16 +04:00
#if STATIC_COMPILER
internal static void HideFromJava(PropertyBuilder pb)
{
if(hideFromJavaAttribute == null)
{
hideFromJavaAttribute = new CustomAttributeBuilder(typeofHideFromJavaAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
}
pb.SetCustomAttribute(hideFromJavaAttribute);
}
#endif // STATIC_COMPILER
#endif // !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
internal static bool IsHideFromJava(Type type)
{
return IsDefined(type, typeofHideFromJavaAttribute);
}
2005-06-01 13:49:30 +04:00
internal static bool IsHideFromJava(MemberInfo mi)
{
// NOTE all privatescope fields and methods are "hideFromJava"
// because Java cannot deal with the potential name clashes
FieldInfo fi = mi as FieldInfo;
if(fi != null && (fi.Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.PrivateScope)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
return true;
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
MethodBase mb = mi as MethodBase;
if(mb != null && (mb.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
return true;
2003-11-17 15:01:50 +03:00
}
2005-12-07 12:06:32 +03:00
return IsDefined(mi, typeofHideFromJavaAttribute);
2003-11-17 15:01:50 +03:00
}
2003-10-17 12:08:31 +04:00
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER && !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal static void SetImplementsAttribute(TypeBuilder typeBuilder, TypeWrapper[] ifaceWrappers)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if(ifaceWrappers != null && ifaceWrappers.Length != 0)
{
string[] interfaces = new string[ifaceWrappers.Length];
for(int i = 0; i < interfaces.Length; i++)
{
interfaces[i] = ifaceWrappers[i].Name;
}
if(implementsAttribute == null)
{
2005-12-07 12:06:32 +03:00
implementsAttribute = typeofImplementsAttribute.GetConstructor(new Type[] { typeof(string[]) });
2005-06-01 13:49:30 +04:00
}
typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(implementsAttribute, new object[] { interfaces }));
}
}
2005-12-07 12:06:32 +03:00
#endif
internal static bool IsGhostInterface(Type type)
{
return IsDefined(type, typeofGhostInterfaceAttribute);
}
internal static bool IsRemappedType(Type type)
{
return IsDefined(type, typeofRemappedTypeAttribute);
}
internal static bool IsExceptionIsUnsafeForMapping(Type type)
{
return IsDefined(type, typeofExceptionIsUnsafeForMappingAttribute);
}
#if !COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
// this method compares t1 and t2 by name
// if the type name and assembly name (ignoring the version and strong name) match
// the type are considered the same
private static bool MatchTypes(Type t1, Type t2)
{
return t1.FullName == t2.FullName
&& t1.Assembly.GetName().Name == t2.Assembly.GetName().Name;
}
#endif
internal static object GetConstantValue(FieldInfo field)
{
#if !STATIC_COMPILER
if(!field.DeclaringType.Assembly.ReflectionOnly)
{
// In Java, instance fields can also have a ConstantValue attribute so we emulate that
// with ConstantValueAttribute (for consumption by ikvmstub only)
object[] attrib = field.GetCustomAttributes(typeof(ConstantValueAttribute), false);
if(attrib.Length == 1)
{
return ((ConstantValueAttribute)attrib[0]).GetConstantValue();
}
return null;
}
else
#endif
{
#if !COMPACT_FRAMEWORK
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(field))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofConstantValueAttribute))
{
return cad.ConstructorArguments[0].Value;
}
}
#endif
return null;
}
}
2005-12-07 12:06:32 +03:00
internal static ModifiersAttribute GetModifiersAttribute(Type type)
{
#if !STATIC_COMPILER
if(!type.Assembly.ReflectionOnly)
2005-12-07 12:06:32 +03:00
{
object[] attr = type.GetCustomAttributes(typeof(ModifiersAttribute), false);
return attr.Length == 1 ? (ModifiersAttribute)attr[0] : null;
}
else
#endif
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(type))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, typeofModifiersAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
2006-04-05 12:18:58 +04:00
if(args.Count == 2)
{
return new ModifiersAttribute((Modifiers)args[0].Value, (bool)args[1].Value);
}
2005-12-07 12:06:32 +03:00
return new ModifiersAttribute((Modifiers)args[0].Value);
}
}
#endif
2005-12-07 12:06:32 +03:00
return null;
}
}
2004-08-17 13:05:21 +04:00
internal static ModifiersAttribute GetModifiersAttribute(PropertyInfo property)
{
#if !STATIC_COMPILER
if (!property.DeclaringType.Assembly.ReflectionOnly)
{
object[] attr = property.GetCustomAttributes(typeof(ModifiersAttribute), false);
return attr.Length == 1 ? (ModifiersAttribute)attr[0] : null;
}
else
#endif
{
#if !COMPACT_FRAMEWORK
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(property))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofModifiersAttribute))
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
if(args.Count == 2)
{
return new ModifiersAttribute((Modifiers)args[0].Value, (bool)args[1].Value);
}
return new ModifiersAttribute((Modifiers)args[0].Value);
}
}
#endif
return null;
}
}
2006-04-05 12:18:58 +04:00
internal static ExModifiers GetModifiers(MethodBase mb, bool assemblyIsPrivate)
2003-10-17 12:08:31 +04:00
{
#if !STATIC_COMPILER
if(!mb.DeclaringType.Assembly.ReflectionOnly)
2005-06-01 13:49:30 +04:00
{
object[] customAttribute = mb.GetCustomAttributes(typeof(ModifiersAttribute), false);
if(customAttribute.Length == 1)
{
ModifiersAttribute mod = (ModifiersAttribute)customAttribute[0];
return new ExModifiers(mod.Modifiers, mod.IsInternal);
}
}
else
#endif
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(mb))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, typeofModifiersAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
2006-04-05 12:18:58 +04:00
if(args.Count == 2)
{
return new ExModifiers((Modifiers)args[0].Value, (bool)args[1].Value);
}
return new ExModifiers((Modifiers)args[0].Value, false);
2005-12-07 12:06:32 +03:00
}
}
#endif
2005-06-01 13:49:30 +04:00
}
Modifiers modifiers = 0;
if(mb.IsPublic)
{
modifiers |= Modifiers.Public;
}
else if(mb.IsPrivate)
{
modifiers |= Modifiers.Private;
}
else if(mb.IsFamily || mb.IsFamilyOrAssembly)
{
modifiers |= Modifiers.Protected;
}
else if(assemblyIsPrivate)
{
modifiers |= Modifiers.Private;
}
// NOTE Java doesn't support non-virtual methods, but we set the Final modifier for
// non-virtual methods to approximate the semantics
if((mb.IsFinal || (!mb.IsVirtual && ((modifiers & Modifiers.Private) == 0))) && !mb.IsStatic && !mb.IsConstructor)
{
modifiers |= Modifiers.Final;
}
if(mb.IsAbstract)
{
modifiers |= Modifiers.Abstract;
}
else
{
// Some .NET interfaces (like System._AppDomain) have synchronized methods,
// Java doesn't allow synchronized on an abstract methods, so we ignore it for
// abstract methods.
if((mb.GetMethodImplementationFlags() & MethodImplAttributes.Synchronized) != 0)
{
modifiers |= Modifiers.Synchronized;
}
}
if(mb.IsStatic)
{
modifiers |= Modifiers.Static;
}
if((mb.Attributes & MethodAttributes.PinvokeImpl) != 0)
{
modifiers |= Modifiers.Native;
}
2005-10-01 15:16:11 +04:00
ParameterInfo[] parameters = mb.GetParameters();
2005-12-07 12:06:32 +03:00
if(parameters.Length > 0 && IsDefined(parameters[parameters.Length - 1], typeof(ParamArrayAttribute)))
2005-10-01 15:16:11 +04:00
{
modifiers |= Modifiers.VarArgs;
}
2006-04-05 12:18:58 +04:00
return new ExModifiers(modifiers, false);
2003-10-17 12:08:31 +04:00
}
2003-05-30 16:08:59 +04:00
2006-04-05 12:18:58 +04:00
internal static ExModifiers GetModifiers(FieldInfo fi, bool assemblyIsPrivate)
2003-05-30 16:08:59 +04:00
{
#if !STATIC_COMPILER
if(!fi.DeclaringType.Assembly.ReflectionOnly)
{
object[] customAttribute = fi.GetCustomAttributes(typeof(ModifiersAttribute), false);
if(customAttribute.Length == 1)
{
ModifiersAttribute mod = (ModifiersAttribute)customAttribute[0];
return new ExModifiers(mod.Modifiers, mod.IsInternal);
}
}
else
#endif
2005-12-07 12:06:32 +03:00
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(fi))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, typeofModifiersAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
2006-04-05 12:18:58 +04:00
if(args.Count == 2)
{
return new ExModifiers((Modifiers)args[0].Value, (bool)args[1].Value);
}
return new ExModifiers((Modifiers)args[0].Value, false);
2005-12-07 12:06:32 +03:00
}
}
#endif
2005-06-01 13:49:30 +04:00
}
Modifiers modifiers = 0;
if(fi.IsPublic)
{
modifiers |= Modifiers.Public;
}
else if(fi.IsPrivate)
{
modifiers |= Modifiers.Private;
}
else if(fi.IsFamily || fi.IsFamilyOrAssembly)
{
modifiers |= Modifiers.Protected;
}
else if(assemblyIsPrivate)
{
modifiers |= Modifiers.Private;
}
if(fi.IsInitOnly || fi.IsLiteral)
{
modifiers |= Modifiers.Final;
}
if(fi.IsNotSerialized)
{
modifiers |= Modifiers.Transient;
}
if(fi.IsStatic)
{
modifiers |= Modifiers.Static;
}
2006-10-04 16:51:19 +04:00
if(Array.IndexOf(fi.GetRequiredCustomModifiers(), typeof(System.Runtime.CompilerServices.IsVolatile)) != -1)
{
modifiers |= Modifiers.Volatile;
}
2006-04-05 12:18:58 +04:00
return new ExModifiers(modifiers, false);
2003-05-30 16:08:59 +04:00
}
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER && !COMPACT_FRAMEWORK
2006-04-05 12:18:58 +04:00
internal static void SetModifiers(MethodBuilder mb, Modifiers modifiers, bool isInternal)
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder;
if (isInternal)
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, typeof(bool) }), new object[] { modifiers, isInternal });
}
else
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers });
}
2005-06-01 13:49:30 +04:00
mb.SetCustomAttribute(customAttributeBuilder);
2003-05-30 16:08:59 +04:00
}
2006-04-05 12:18:58 +04:00
internal static void SetModifiers(ConstructorBuilder cb, Modifiers modifiers, bool isInternal)
2003-10-17 12:08:31 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder;
if (isInternal)
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, typeof(bool) }), new object[] { modifiers, isInternal });
}
else
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers });
}
2005-06-01 13:49:30 +04:00
cb.SetCustomAttribute(customAttributeBuilder);
2003-10-17 12:08:31 +04:00
}
2006-04-05 12:18:58 +04:00
internal static void SetModifiers(FieldBuilder fb, Modifiers modifiers, bool isInternal)
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder;
if (isInternal)
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, typeof(bool) }), new object[] { modifiers, isInternal });
}
else
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers });
}
2005-06-01 13:49:30 +04:00
fb.SetCustomAttribute(customAttributeBuilder);
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetModifiers(PropertyBuilder pb, Modifiers modifiers, bool isInternal)
{
CustomAttributeBuilder customAttributeBuilder;
if (isInternal)
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, typeof(bool) }), new object[] { modifiers, isInternal });
}
else
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers });
}
pb.SetCustomAttribute(customAttributeBuilder);
}
2006-04-05 12:18:58 +04:00
internal static void SetModifiers(TypeBuilder tb, Modifiers modifiers, bool isInternal)
2003-05-30 16:08:59 +04:00
{
2006-04-05 12:18:58 +04:00
CustomAttributeBuilder customAttributeBuilder;
if (isInternal)
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers, typeof(bool) }), new object[] { modifiers, isInternal });
}
else
{
customAttributeBuilder = new CustomAttributeBuilder(typeofModifiersAttribute.GetConstructor(new Type[] { typeofModifiers }), new object[] { modifiers });
}
2005-06-01 13:49:30 +04:00
tb.SetCustomAttribute(customAttributeBuilder);
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetNameSig(MethodBase mb, string name, string sig)
2003-07-24 11:29:51 +04:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeofNameSigAttribute.GetConstructor(new Type[] { typeof(string), typeof(string) }), new object[] { name, sig });
2005-06-01 13:49:30 +04:00
MethodBuilder method = mb as MethodBuilder;
if(method != null)
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
method.SetCustomAttribute(customAttributeBuilder);
2004-05-14 13:31:54 +04:00
}
2005-06-01 13:49:30 +04:00
else
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
((ConstructorBuilder)mb).SetCustomAttribute(customAttributeBuilder);
2004-05-14 13:31:54 +04:00
}
2003-08-05 18:07:22 +04:00
}
2003-07-24 11:29:51 +04:00
2005-06-01 13:49:30 +04:00
internal static void SetNameSig(FieldBuilder fb, string name, string sig)
2003-12-24 14:51:41 +03:00
{
2005-12-07 12:06:32 +03:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeofNameSigAttribute.GetConstructor(new Type[] { typeof(string), typeof(string) }), new object[] { name, sig });
2005-06-01 13:49:30 +04:00
fb.SetCustomAttribute(customAttributeBuilder);
2003-12-24 14:51:41 +03:00
}
2005-06-01 13:49:30 +04:00
internal static byte[] FreezeDryType(Type type)
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
System.IO.MemoryStream mem = new System.IO.MemoryStream();
System.IO.BinaryWriter bw = new System.IO.BinaryWriter(mem, System.Text.UTF8Encoding.UTF8);
bw.Write((short)1);
bw.Write(type.FullName);
bw.Write((short)0);
return mem.ToArray();
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2005-07-07 15:24:08 +04:00
internal static void SetInnerClass(TypeBuilder typeBuilder, string innerClass, Modifiers modifiers)
2003-05-30 16:08:59 +04:00
{
2005-12-07 12:06:32 +03:00
Type[] argTypes = new Type[] { typeof(string), typeofModifiers };
2005-07-07 15:24:08 +04:00
object[] args = new object[] { innerClass, modifiers };
2005-12-07 12:06:32 +03:00
ConstructorInfo ci = typeofInnerClassAttribute.GetConstructor(argTypes);
2005-06-01 13:49:30 +04:00
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(ci, args);
typeBuilder.SetCustomAttribute(customAttributeBuilder);
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
internal static void SetSourceFile(TypeBuilder typeBuilder, string filename)
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
if(sourceFileAttribute == null)
2003-08-21 14:06:34 +04:00
{
2005-12-07 12:06:32 +03:00
sourceFileAttribute = typeofSourceFileAttribute.GetConstructor(new Type[] { typeof(string) });
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(sourceFileAttribute, new object[] { filename }));
2003-05-30 16:08:59 +04:00
}
2005-12-07 12:06:32 +03:00
internal static void SetSourceFile(ModuleBuilder moduleBuilder, string filename)
{
if(sourceFileAttribute == null)
{
sourceFileAttribute = typeofSourceFileAttribute.GetConstructor(new Type[] { typeof(string) });
}
moduleBuilder.SetCustomAttribute(new CustomAttributeBuilder(sourceFileAttribute, new object[] { filename }));
}
2005-08-22 16:42:02 +04:00
internal static void SetLineNumberTable(MethodBase mb, IKVM.Attributes.LineNumberTableAttribute.LineNumberWriter writer)
2003-05-30 16:08:59 +04:00
{
2005-08-22 16:42:02 +04:00
object arg;
ConstructorInfo con;
if(writer.Count == 1)
2005-06-01 13:49:30 +04:00
{
2005-08-22 16:42:02 +04:00
if(lineNumberTableAttribute2 == null)
{
2005-12-07 12:06:32 +03:00
lineNumberTableAttribute2 = typeofLineNumberTableAttribute.GetConstructor(new Type[] { typeof(ushort) });
2005-08-22 16:42:02 +04:00
}
con = lineNumberTableAttribute2;
arg = (ushort)writer.LineNo;
}
else
{
if(lineNumberTableAttribute1 == null)
{
2005-12-07 12:06:32 +03:00
lineNumberTableAttribute1 = typeofLineNumberTableAttribute.GetConstructor(new Type[] { typeof(byte[]) });
2005-08-22 16:42:02 +04:00
}
con = lineNumberTableAttribute1;
arg = writer.ToArray();
2005-06-01 13:49:30 +04:00
}
if(mb is ConstructorBuilder)
{
2005-08-22 16:42:02 +04:00
((ConstructorBuilder)mb).SetCustomAttribute(new CustomAttributeBuilder(con, new object[] { arg }));
2005-06-01 13:49:30 +04:00
}
else
{
2005-08-22 16:42:02 +04:00
((MethodBuilder)mb).SetCustomAttribute(new CustomAttributeBuilder(con, new object[] { arg }));
2005-06-01 13:49:30 +04:00
}
2003-05-30 16:08:59 +04:00
}
2005-10-01 15:16:11 +04:00
internal static void SetEnclosingMethodAttribute(TypeBuilder tb, string className, string methodName, string methodSig)
{
if(enclosingMethodAttribute == null)
{
2005-12-07 12:06:32 +03:00
enclosingMethodAttribute = typeofEnclosingMethodAttribute.GetConstructor(new Type[] { typeof(string), typeof(string), typeof(string) });
2005-10-01 15:16:11 +04:00
}
tb.SetCustomAttribute(new CustomAttributeBuilder(enclosingMethodAttribute, new object[] { className, methodName, methodSig }));
}
internal static void SetSignatureAttribute(TypeBuilder tb, string signature)
{
if(signatureAttribute == null)
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute.GetConstructor(new Type[] { typeof(string) });
2005-10-01 15:16:11 +04:00
}
tb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { signature }));
}
internal static void SetSignatureAttribute(FieldBuilder fb, string signature)
{
if(signatureAttribute == null)
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute.GetConstructor(new Type[] { typeof(string) });
2005-10-01 15:16:11 +04:00
}
fb.SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { signature }));
}
internal static void SetSignatureAttribute(MethodBase mb, string signature)
{
if(signatureAttribute == null)
{
2005-12-07 12:06:32 +03:00
signatureAttribute = typeofSignatureAttribute.GetConstructor(new Type[] { typeof(string) });
2005-10-01 15:16:11 +04:00
}
if(mb is ConstructorBuilder)
{
((ConstructorBuilder)mb).SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { signature }));
}
else
{
((MethodBuilder)mb).SetCustomAttribute(new CustomAttributeBuilder(signatureAttribute, new object[] { signature }));
}
}
internal static void SetParamArrayAttribute(ParameterBuilder pb)
{
if(paramArrayAttribute == null)
{
paramArrayAttribute = new CustomAttributeBuilder(typeof(ParamArrayAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
}
pb.SetCustomAttribute(paramArrayAttribute);
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER && !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
internal static NameSigAttribute GetNameSig(FieldInfo field)
{
#if !STATIC_COMPILER
if(!field.DeclaringType.Assembly.ReflectionOnly)
{
object[] attr = field.GetCustomAttributes(typeof(NameSigAttribute), false);
return attr.Length == 1 ? (NameSigAttribute)attr[0] : null;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(field))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, typeofNameSigAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new NameSigAttribute((string)args[0].Value, (string)args[1].Value);
}
}
#endif
2005-12-07 12:06:32 +03:00
return null;
}
}
internal static NameSigAttribute GetNameSig(MethodBase method)
{
#if !STATIC_COMPILER
if(!method.DeclaringType.Assembly.ReflectionOnly)
{
object[] attr = method.GetCustomAttributes(typeof(NameSigAttribute), false);
return attr.Length == 1 ? (NameSigAttribute)attr[0] : null;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(method))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, typeofNameSigAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new NameSigAttribute((string)args[0].Value, (string)args[1].Value);
}
}
#endif
2005-12-07 12:06:32 +03:00
return null;
}
}
#if !COMPACT_FRAMEWORK
2005-12-19 18:12:49 +03:00
internal static T[] DecodeArray<T>(CustomAttributeTypedArgument arg)
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> elems = (IList<CustomAttributeTypedArgument>)arg.Value;
T[] arr = new T[elems.Count];
for(int i = 0; i < arr.Length; i++)
{
arr[i] = (T)elems[i].Value;
}
return arr;
}
#endif
internal static ImplementsAttribute GetImplements(Type type)
{
#if !STATIC_COMPILER
if(!type.Assembly.ReflectionOnly)
{
object[] attribs = type.GetCustomAttributes(typeof(ImplementsAttribute), false);
return attribs.Length == 1 ? (ImplementsAttribute)attribs[0] : null;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(type))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, typeofImplementsAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new ImplementsAttribute(DecodeArray<string>(args[0]));
}
}
#endif
2005-12-07 12:06:32 +03:00
return null;
}
}
2006-07-21 14:18:13 +04:00
internal static ThrowsAttribute GetThrows(MethodBase mb)
{
#if !STATIC_COMPILER
if(!mb.DeclaringType.Assembly.ReflectionOnly)
{
object[] attribs = mb.GetCustomAttributes(typeof(ThrowsAttribute), false);
return attribs.Length == 1 ? (ThrowsAttribute)attribs[0] : null;
}
else
#endif
2006-07-21 14:18:13 +04:00
{
#if !COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(mb))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofThrowsAttribute))
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new ThrowsAttribute(DecodeArray<string>(args[0]));
}
}
#endif
2006-07-21 14:18:13 +04:00
return null;
}
}
internal static string[] GetNonNestedInnerClasses(Type t)
{
#if !STATIC_COMPILER
if(!t.Assembly.ReflectionOnly)
{
object[] attribs = t.GetCustomAttributes(typeof(NonNestedInnerClassAttribute), false);
string[] classes = new string[attribs.Length];
for (int i = 0; i < attribs.Length; i++)
{
classes[i] = ((NonNestedInnerClassAttribute)attribs[i]).InnerClassName;
}
return classes;
}
else
#endif
{
List<string> list = new List<string>();
#if !COMPACT_FRAMEWORK
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(t))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofNonNestedInnerClassAttribute))
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
list.Add((string)args[0].Value);
}
}
#endif
return list.ToArray();
}
}
internal static string GetNonNestedOuterClasses(Type t)
{
#if !STATIC_COMPILER
if(!t.Assembly.ReflectionOnly)
{
object[] attribs = t.GetCustomAttributes(typeof(NonNestedOuterClassAttribute), false);
return attribs.Length == 1 ? ((NonNestedOuterClassAttribute)attribs[0]).OuterClassName : null;
}
else
#endif
{
#if !COMPACT_FRAMEWORK
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(t))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofNonNestedOuterClassAttribute))
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return (string)args[0].Value;
}
}
#endif
return null;
}
}
2006-07-21 14:18:13 +04:00
internal static SignatureAttribute GetSignature(MethodBase mb)
{
#if !STATIC_COMPILER
if(!mb.DeclaringType.Assembly.ReflectionOnly)
2006-07-21 14:18:13 +04:00
{
object[] attribs = mb.GetCustomAttributes(typeof(SignatureAttribute), false);
return attribs.Length == 1 ? (SignatureAttribute)attribs[0] : null;
}
else
#endif
{
#if !COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(mb))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofSignatureAttribute))
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new SignatureAttribute((string)args[0].Value);
}
}
#endif
2006-07-21 14:18:13 +04:00
return null;
}
}
internal static SignatureAttribute GetSignature(Type type)
{
#if !STATIC_COMPILER
if(!type.Assembly.ReflectionOnly)
{
object[] attribs = type.GetCustomAttributes(typeof(SignatureAttribute), false);
return attribs.Length == 1 ? (SignatureAttribute)attribs[0] : null;
}
else
#endif
2006-07-21 14:18:13 +04:00
{
#if !COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(type))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofSignatureAttribute))
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new SignatureAttribute((string)args[0].Value);
}
}
#endif
2006-07-21 14:18:13 +04:00
return null;
}
}
internal static SignatureAttribute GetSignature(FieldInfo fi)
{
#if !STATIC_COMPILER
if(!fi.DeclaringType.Assembly.ReflectionOnly)
{
object[] attribs = fi.GetCustomAttributes(typeof(SignatureAttribute), false);
return attribs.Length == 1 ? (SignatureAttribute)attribs[0] : null;
}
else
#endif
2006-07-21 14:18:13 +04:00
{
#if !COMPACT_FRAMEWORK
2006-07-21 14:18:13 +04:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(fi))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofSignatureAttribute))
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new SignatureAttribute((string)args[0].Value);
}
}
#endif
2006-07-21 14:18:13 +04:00
return null;
}
}
2005-12-07 12:06:32 +03:00
internal static InnerClassAttribute GetInnerClass(Type type)
{
#if !STATIC_COMPILER
if(!type.Assembly.ReflectionOnly)
{
object[] attribs = type.GetCustomAttributes(typeof(InnerClassAttribute), false);
return attribs.Length == 1 ? (InnerClassAttribute)attribs[0] : null;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(type))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, typeofInnerClassAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new InnerClassAttribute((string)args[0].Value, (Modifiers)args[1].Value);
}
}
#endif
2005-12-07 12:06:32 +03:00
return null;
}
}
internal static RemappedInterfaceMethodAttribute[] GetRemappedInterfaceMethods(Type type)
{
#if !STATIC_COMPILER
if(!type.Assembly.ReflectionOnly)
{
object[] attr = type.GetCustomAttributes(typeof(RemappedInterfaceMethodAttribute), false);
RemappedInterfaceMethodAttribute[] attr1 = new RemappedInterfaceMethodAttribute[attr.Length];
Array.Copy(attr, attr1, attr.Length);
return attr1;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
List<RemappedInterfaceMethodAttribute> attrs = new List<RemappedInterfaceMethodAttribute>();
#if !COMPACT_FRAMEWORK
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(type))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofRemappedInterfaceMethodAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
attrs.Add(new RemappedInterfaceMethodAttribute((string)args[0].Value, (string)args[1].Value));
2005-12-07 12:06:32 +03:00
}
}
#endif
2005-12-07 12:06:32 +03:00
return attrs.ToArray();
}
}
internal static RemappedTypeAttribute GetRemappedType(Type type)
{
#if !STATIC_COMPILER
if(!type.Assembly.ReflectionOnly)
2005-12-07 12:06:32 +03:00
{
object[] attribs = type.GetCustomAttributes(typeof(RemappedTypeAttribute), false);
return attribs.Length == 1 ? (RemappedTypeAttribute)attribs[0] : null;
}
else
#endif
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(type))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, typeofRemappedTypeAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
return new RemappedTypeAttribute((Type)args[0].Value);
}
}
#endif
2005-12-07 12:06:32 +03:00
return null;
}
}
internal static RemappedClassAttribute[] GetRemappedClasses(Assembly coreAssembly)
{
#if !STATIC_COMPILER
if(!coreAssembly.ReflectionOnly)
{
object[] attr = coreAssembly.GetCustomAttributes(typeof(RemappedClassAttribute), false);
RemappedClassAttribute[] attr1 = new RemappedClassAttribute[attr.Length];
Array.Copy(attr, attr1, attr.Length);
return attr1;
}
else
#endif
2005-12-07 12:06:32 +03:00
{
List<RemappedClassAttribute> attrs = new List<RemappedClassAttribute>();
#if !COMPACT_FRAMEWORK
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(coreAssembly))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofRemappedClassAttribute))
2005-12-07 12:06:32 +03:00
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
attrs.Add(new RemappedClassAttribute((string)args[0].Value, (Type)args[1].Value));
2005-12-07 12:06:32 +03:00
}
}
#endif
2005-12-07 12:06:32 +03:00
return attrs.ToArray();
}
}
2006-04-11 18:59:43 +04:00
internal static string GetAnnotationAttributeType(Type type)
{
#if !STATIC_COMPILER
if(!type.Assembly.ReflectionOnly)
{
object[] attr = type.GetCustomAttributes(typeof(AnnotationAttributeAttribute), false);
if(attr.Length == 1)
{
return ((AnnotationAttributeAttribute)attr[0]).AttributeType;
}
return null;
}
else
#endif
{
#if !COMPACT_FRAMEWORK
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(type))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofAnnotationAttributeAttribute))
{
return (string)cad.ConstructorArguments[0].Value;
}
}
#endif
return null;
2006-04-11 18:59:43 +04:00
}
}
internal static AssemblyName[] GetInternalsVisibleToAttributes(Assembly assembly)
{
List<AssemblyName> list = new List<AssemblyName>();
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(assembly))
{
if(cad.Constructor.DeclaringType == typeof(System.Runtime.CompilerServices.InternalsVisibleToAttribute))
{
try
{
list.Add(new AssemblyName((string)cad.ConstructorArguments[0].Value));
}
catch
{
// HACK since there is no list of exception that the AssemblyName constructor can throw, we simply catch all
}
}
}
return list.ToArray();
}
2005-12-07 12:06:32 +03:00
internal static bool IsDefined(Module mod, Type attribute)
{
#if !STATIC_COMPILER
if(!mod.Assembly.ReflectionOnly)
{
return mod.IsDefined(attribute, false);
}
else
#endif
2005-12-07 12:06:32 +03:00
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(mod))
{
// NOTE we don't support subtyping relations!
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, attribute))
2005-12-07 12:06:32 +03:00
{
return true;
}
}
#endif
2005-12-07 12:06:32 +03:00
return false;
}
}
internal static bool IsDefined(Assembly asm, Type attribute)
{
#if !STATIC_COMPILER
if(!asm.ReflectionOnly)
2005-12-07 12:06:32 +03:00
{
return asm.IsDefined(attribute, false);
}
else
#endif
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(asm))
{
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, attribute))
2005-12-07 12:06:32 +03:00
{
return true;
}
}
#endif
2005-12-07 12:06:32 +03:00
return false;
}
}
internal static bool IsDefined(Type type, Type attribute)
{
#if !STATIC_COMPILER
if(!type.Assembly.ReflectionOnly)
{
return type.IsDefined(attribute, false);
}
else
#endif
2005-12-07 12:06:32 +03:00
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(type))
{
// NOTE we don't support subtyping relations!
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, attribute))
2005-12-07 12:06:32 +03:00
{
return true;
}
}
#endif
2005-12-07 12:06:32 +03:00
return false;
}
}
internal static bool IsDefined(ParameterInfo pi, Type attribute)
{
#if !STATIC_COMPILER
if(!pi.Member.DeclaringType.Assembly.ReflectionOnly)
2005-12-07 12:06:32 +03:00
{
return pi.IsDefined(attribute, false);
}
else
#endif
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(pi))
{
// NOTE we don't support subtyping relations!
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, attribute))
2005-12-07 12:06:32 +03:00
{
return true;
}
}
#endif
2005-12-07 12:06:32 +03:00
return false;
}
}
internal static bool IsDefined(MemberInfo member, Type attribute)
{
#if !STATIC_COMPILER
if(!member.DeclaringType.Assembly.ReflectionOnly)
2005-12-07 12:06:32 +03:00
{
return member.IsDefined(attribute, false);
}
else
#endif
{
#if !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(member))
{
// NOTE we don't support subtyping relations!
2006-07-21 14:18:13 +04:00
if(MatchTypes(cad.Constructor.DeclaringType, attribute))
2005-12-07 12:06:32 +03:00
{
return true;
}
}
#endif
2005-12-07 12:06:32 +03:00
return false;
}
}
internal static bool IsJavaModule(Module mod)
{
return IsDefined(mod, typeofJavaModuleAttribute);
}
2006-10-09 12:29:42 +04:00
internal static object[] GetJavaModuleAttributes(Module mod)
{
#if !STATIC_COMPILER
if(!mod.Assembly.ReflectionOnly)
{
return mod.GetCustomAttributes(typeofJavaModuleAttribute, false);
}
else
#endif
2006-10-09 16:32:33 +04:00
{
ArrayList attrs = new ArrayList();
#if !COMPACT_FRAMEWORK
2006-10-09 16:32:33 +04:00
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(mod))
{
if(MatchTypes(cad.Constructor.DeclaringType, typeofJavaModuleAttribute))
{
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
if(args.Count == 0)
{
attrs.Add(new JavaModuleAttribute());
}
else
{
attrs.Add(new JavaModuleAttribute(DecodeArray<string>(args[0])));
}
}
}
#endif
2006-10-09 16:32:33 +04:00
return attrs.ToArray();
}
2006-10-09 12:29:42 +04:00
}
2005-12-07 12:06:32 +03:00
internal static bool IsNoPackagePrefix(Type type)
{
return IsDefined(type, typeofNoPackagePrefixAttribute) || IsDefined(type.Assembly, typeofNoPackagePrefixAttribute);
}
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER && !COMPACT_FRAMEWORK
2005-12-07 12:06:32 +03:00
internal static void SetRemappedClass(AssemblyBuilder assemblyBuilder, string name, Type shadowType)
{
ConstructorInfo remappedClassAttribute = typeofRemappedClassAttribute.GetConstructor(new Type[] { typeof(string), typeof(Type) });
assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(remappedClassAttribute, new object[] { name, shadowType }));
}
internal static void SetRemappedType(TypeBuilder typeBuilder, Type shadowType)
{
ConstructorInfo remappedTypeAttribute = typeofRemappedTypeAttribute.GetConstructor(new Type[] { typeof(Type) });
typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(remappedTypeAttribute, new object[] { shadowType }));
}
internal static void SetRemappedInterfaceMethod(TypeBuilder typeBuilder, string name, string mappedTo)
{
CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofRemappedInterfaceMethodAttribute.GetConstructor(new Type[] { typeof(string), typeof(string) }), new object[] { name, mappedTo } );
typeBuilder.SetCustomAttribute(cab);
}
internal static void SetExceptionIsUnsafeForMapping(TypeBuilder typeBuilder)
{
CustomAttributeBuilder cab = new CustomAttributeBuilder(typeofExceptionIsUnsafeForMappingAttribute.GetConstructor(Type.EmptyTypes), new object[0]);
typeBuilder.SetCustomAttribute(cab);
}
internal static void SetConstantValue(FieldBuilder field, object constantValue)
{
2007-04-05 16:50:59 +04:00
CustomAttributeBuilder constantValueAttrib;
try
{
constantValueAttrib = new CustomAttributeBuilder(typeofConstantValueAttribute.GetConstructor(new Type[] { constantValue.GetType() }), new object[] { constantValue });
}
catch (OverflowException)
{
// FXBUG for char values > 32K .NET (1.1 and 2.0) throws an exception (because it tries to convert to Int16)
if (constantValue is char)
{
// we use the int constant value instead, the stub generator can handle that
constantValueAttrib = new CustomAttributeBuilder(typeofConstantValueAttribute.GetConstructor(new Type[] { typeof(int) }), new object[] { (int)(char)constantValue });
}
else
{
throw;
}
}
2005-12-07 12:06:32 +03:00
field.SetCustomAttribute(constantValueAttrib);
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER && !COMPACT_FRAMEWORK
2003-05-30 16:08:59 +04:00
}
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
abstract class Annotation
{
2006-04-20 11:30:59 +04:00
// NOTE this method returns null if the type could not be found
2006-06-15 16:29:11 +04:00
// or if the type is not a Custom Attribute and we're not in the static compiler
2006-04-20 11:30:59 +04:00
internal static Annotation Load(ClassLoaderWrapper loader, object[] def)
{
Debug.Assert(def[0].Equals(AnnotationDefaultAttribute.TAG_ANNOTATION));
string annotationClass = (string)def[1];
2006-06-15 16:29:11 +04:00
#if !STATIC_COMPILER
if(!annotationClass.EndsWith("$Annotation;")
&& !annotationClass.EndsWith("$Annotation$__ReturnValue;")
&& !annotationClass.EndsWith("$Annotation$__Multiple;"))
2006-06-15 16:29:11 +04:00
{
// we don't want to try to load an annotation in dynamic mode,
// unless it is a .NET custom attribute (which can affect runtime behavior)
return null;
}
#endif
2006-04-20 11:30:59 +04:00
try
{
TypeWrapper annot = loader.RetTypeWrapperFromSig(annotationClass.Replace('/', '.'));
return annot.Annotation;
}
#if STATIC_COMPILER
catch(ClassNotFoundException x)
{
StaticCompiler.IssueMessage(Message.ClassNotFound, x.Message);
return null;
}
#endif
catch (RetargetableJavaException)
2006-04-20 11:30:59 +04:00
{
Tracer.Warning(Tracer.Compiler, "Unable to load annotation class {0}", annotationClass);
return null;
}
}
2006-04-23 14:46:51 +04:00
internal static bool HasRetentionPolicyRuntime(object[] annotations)
{
if(annotations != null)
{
foreach(object[] def in annotations)
{
if(def[1].Equals("Ljava/lang/annotation/Retention;"))
{
for(int i = 2; i < def.Length; i += 2)
{
if(def[i].Equals("value"))
{
object[] val = def[i + 1] as object[];
if(val != null
&& val.Length == 3
&& val[0].Equals(AnnotationDefaultAttribute.TAG_ENUM)
&& val[1].Equals("Ljava/lang/annotation/RetentionPolicy;")
&& val[2].Equals("RUNTIME"))
{
return true;
}
}
}
}
}
}
return false;
}
protected static object QualifyClassNames(ClassLoaderWrapper loader, object annotation)
{
bool copy = false;
object[] def = (object[])annotation;
for(int i = 3; i < def.Length; i += 2)
{
object[] val = def[i] as object[];
if(val != null)
{
object[] newval = ValueQualifyClassNames(loader, val);
if(newval != val)
{
if(!copy)
{
copy = true;
object[] newdef = new object[def.Length];
Array.Copy(def, newdef, def.Length);
def = newdef;
}
def[i] = newval;
}
}
}
return def;
}
private static object[] ValueQualifyClassNames(ClassLoaderWrapper loader, object[] val)
{
if(val[0].Equals(AnnotationDefaultAttribute.TAG_ANNOTATION))
{
return (object[])QualifyClassNames(loader, val);
}
else if(val[0].Equals(AnnotationDefaultAttribute.TAG_CLASS))
{
string sig = (string)val[1];
if(sig.StartsWith("L"))
{
TypeWrapper tw = loader.LoadClassByDottedNameFast(sig.Substring(1, sig.Length - 2).Replace('/', '.'));
if(tw != null)
{
return new object[] { AnnotationDefaultAttribute.TAG_CLASS, "L" + tw.TypeAsBaseType.AssemblyQualifiedName.Replace('.', '/') + ";" };
}
}
return val;
}
else if(val[0].Equals(AnnotationDefaultAttribute.TAG_ENUM))
{
string sig = (string)val[1];
TypeWrapper tw = loader.LoadClassByDottedNameFast(sig.Substring(1, sig.Length - 2).Replace('/', '.'));
if(tw != null)
{
return new object[] { AnnotationDefaultAttribute.TAG_ENUM, "L" + tw.TypeAsBaseType.AssemblyQualifiedName.Replace('.', '/') + ";", val[2] };
}
return val;
}
else if(val[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY))
{
bool copy = false;
for(int i = 1; i < val.Length; i++)
{
object[] nval = val[i] as object[];
if(nval != null)
{
object newnval = ValueQualifyClassNames(loader, nval);
if(newnval != nval)
{
if(!copy)
{
copy = true;
object[] newval = new object[val.Length];
Array.Copy(val, newval, val.Length);
val = newval;
}
val[i] = newnval;
}
}
}
return val;
}
else
{
throw new InvalidOperationException();
}
}
internal abstract void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation);
internal abstract void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation);
internal abstract void Apply(ClassLoaderWrapper loader, ConstructorBuilder cb, object annotation);
internal abstract void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation);
internal abstract void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation);
internal abstract void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation);
internal abstract void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation);
internal virtual void ApplyReturnValue(ClassLoaderWrapper loader, MethodBuilder mb, ref ParameterBuilder pb, object annotation)
{
}
2005-11-01 17:01:42 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-11-01 17:01:42 +03:00
2006-04-05 12:18:58 +04:00
[Flags]
enum TypeFlags : ushort
{
HasIncompleteInterfaceImplementation = 1,
InternalAccess = 2,
2006-08-21 09:15:51 +04:00
HasStaticInitializer = 4,
VerifyError = 8,
ClassFormatError = 16,
HasUnsupportedAbstractMethods = 32,
2006-04-05 12:18:58 +04:00
}
2006-04-10 13:09:09 +04:00
internal abstract class TypeWrapper
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
private readonly string name; // java name (e.g. java.lang.Object)
private readonly Modifiers modifiers;
2006-04-05 12:18:58 +04:00
private TypeFlags flags;
2005-06-01 13:49:30 +04:00
private MethodWrapper[] methods;
private FieldWrapper[] fields;
private readonly TypeWrapper baseWrapper;
2006-04-10 13:09:09 +04:00
#if !STATIC_COMPILER
2006-03-23 14:57:41 +03:00
private object classObject;
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
internal static readonly TypeWrapper[] EmptyArray = new TypeWrapper[0];
internal const Modifiers UnloadableModifiersHack = Modifiers.Final | Modifiers.Interface | Modifiers.Private;
internal const Modifiers VerifierTypeModifiersHack = Modifiers.Final | Modifiers.Interface;
2003-07-31 16:49:29 +04:00
2006-03-23 14:57:41 +03:00
internal TypeWrapper(Modifiers modifiers, string name, TypeWrapper baseWrapper)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Profiler.Count("TypeWrapper");
// class name should be dotted or null for primitives
Debug.Assert(name == null || name.IndexOf('/') < 0);
2003-08-01 16:12:08 +04:00
2005-06-01 13:49:30 +04:00
this.modifiers = modifiers;
2005-07-20 13:42:11 +04:00
this.name = name == null ? null : String.Intern(name);
2005-06-01 13:49:30 +04:00
this.baseWrapper = baseWrapper;
2006-03-23 14:57:41 +03:00
}
2006-04-10 13:09:09 +04:00
#if !STATIC_COMPILER
2006-03-23 14:57:41 +03:00
internal void SetClassObject(object classObject)
{
this.classObject = classObject;
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
internal object ClassObject
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-09-12 13:57:36 +04:00
Debug.Assert(!IsUnloadable && !IsVerifierType);
2006-03-23 14:57:41 +03:00
lock(this)
{
if(classObject == null)
{
2006-07-06 17:53:51 +04:00
#if !COMPACT_FRAMEWORK
2006-03-23 14:57:41 +03:00
// DynamicTypeWrapper should haved already had SetClassObject explicitly
Debug.Assert(!(this is DynamicTypeWrapper));
2006-07-06 17:53:51 +04:00
#endif // !COMPACT_FRAMEWORK
#if FIRST_PASS
#elif OPENJDK
java.lang.Class clazz = java.lang.Class.newClass();
SetTypeWrapperHack(ref clazz.typeWrapper, this);
classObject = clazz;
#else
2006-08-15 12:50:43 +04:00
classObject = JVM.Library.newClass(this, null, GetClassLoader().GetJavaClassLoader());
#endif
2006-03-23 14:57:41 +03:00
}
}
2005-06-01 13:49:30 +04:00
return classObject;
}
2004-10-19 17:43:55 +04:00
}
2003-05-13 00:00:15 +04:00
// MONOBUG this method is to work around an mcs bug
internal static void SetTypeWrapperHack<T>(ref T field, TypeWrapper type)
{
field = (T)(object)type;
}
2006-03-27 17:59:59 +04:00
internal static TypeWrapper FromClass(object classObject)
{
#if FIRST_PASS
return null;
#elif OPENJDK
// MONOBUG redundant cast to workaround mcs bug
return (TypeWrapper)(object)((java.lang.Class)classObject).typeWrapper;
#else
2006-03-27 17:59:59 +04:00
return (TypeWrapper)JVM.Library.getWrapperFromClass(classObject);
#endif
2006-03-27 17:59:59 +04:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2006-03-27 17:59:59 +04:00
2005-06-01 13:49:30 +04:00
public override string ToString()
2004-12-21 17:59:29 +03:00
{
2005-06-01 13:49:30 +04:00
return GetType().Name + "[" + name + "]";
2004-12-21 17:59:29 +03:00
}
2005-06-01 13:49:30 +04:00
// For UnloadableTypeWrapper it tries to load the type through the specified loader
// and if that fails it throw a NoClassDefFoundError (not a java.lang.NoClassDefFoundError),
// for all other types this is a no-op.
internal virtual TypeWrapper EnsureLoadable(ClassLoaderWrapper loader)
2004-12-21 17:59:29 +03:00
{
2005-06-01 13:49:30 +04:00
return this;
2004-12-21 17:59:29 +03:00
}
2005-02-23 15:56:15 +03:00
2005-06-01 13:49:30 +04:00
internal bool HasIncompleteInterfaceImplementation
2003-05-13 00:00:15 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-04-05 12:18:58 +04:00
return (flags & TypeFlags.HasIncompleteInterfaceImplementation) != 0 || (baseWrapper != null && baseWrapper.HasIncompleteInterfaceImplementation);
2005-06-01 13:49:30 +04:00
}
set
{
2006-04-05 12:18:58 +04:00
// TODO do we need locking here?
if(value)
{
flags |= TypeFlags.HasIncompleteInterfaceImplementation;
}
else
{
flags &= ~TypeFlags.HasIncompleteInterfaceImplementation;
}
2005-06-01 13:49:30 +04:00
}
2003-05-13 00:00:15 +04:00
}
internal bool HasUnsupportedAbstractMethods
{
get
{
foreach(TypeWrapper iface in this.Interfaces)
{
if(iface.HasUnsupportedAbstractMethods)
{
return true;
}
}
return (flags & TypeFlags.HasUnsupportedAbstractMethods) != 0 || (baseWrapper != null && baseWrapper.HasUnsupportedAbstractMethods);
}
set
{
// TODO do we need locking here?
if(value)
{
flags |= TypeFlags.HasUnsupportedAbstractMethods;
}
else
{
flags &= ~TypeFlags.HasUnsupportedAbstractMethods;
}
}
}
2005-06-01 13:49:30 +04:00
internal virtual bool HasStaticInitializer
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-04-05 12:18:58 +04:00
return (flags & TypeFlags.HasStaticInitializer) != 0;
}
set
{
// TODO do we need locking here?
if(value)
{
flags |= TypeFlags.HasStaticInitializer;
}
else
{
flags &= ~TypeFlags.HasStaticInitializer;
}
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
}
2006-08-21 09:15:51 +04:00
internal bool HasVerifyError
{
get
{
return (flags & TypeFlags.VerifyError) != 0;
}
set
{
// TODO do we need locking here?
if(value)
{
flags |= TypeFlags.VerifyError;
}
else
{
flags &= ~TypeFlags.VerifyError;
}
}
}
internal bool HasClassFormatError
{
get
{
return (flags & TypeFlags.ClassFormatError) != 0;
}
set
{
// TODO do we need locking here?
if(value)
{
flags |= TypeFlags.ClassFormatError;
}
else
{
flags &= ~TypeFlags.ClassFormatError;
}
}
}
internal virtual bool IsFakeTypeContainer
{
get
{
return false;
}
}
2005-06-01 13:49:30 +04:00
// a ghost is an interface that appears to be implemented by a .NET type
// (e.g. System.String (aka java.lang.String) appears to implement java.lang.CharSequence,
// so java.lang.CharSequence is a ghost)
internal virtual bool IsGhost
2003-07-31 16:49:29 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return false;
}
2003-07-31 16:49:29 +04:00
}
2005-06-01 13:49:30 +04:00
// is this an array type of which the ultimate element type is a ghost?
internal bool IsGhostArray
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return !IsUnloadable && IsArray && (ElementTypeWrapper.IsGhost || ElementTypeWrapper.IsGhostArray);
2005-06-01 13:49:30 +04:00
}
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual FieldInfo GhostRefField
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException();
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual bool IsRemapped
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return false;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsArray
2003-03-21 16:41:43 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name != null && name[0] == '[';
}
2003-03-21 16:41:43 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE for non-array types this returns 0
internal int ArrayRank
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
int i = 0;
if(name != null)
2003-06-20 17:46:13 +04:00
{
2005-06-01 13:49:30 +04:00
while(name[i] == '[')
{
i++;
}
2003-06-20 17:46:13 +04:00
}
2005-06-01 13:49:30 +04:00
return i;
2003-01-06 16:56:37 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal bool IsNonPrimitiveValueType
2003-04-14 13:41:58 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return this != VerifierTypeWrapper.Null && !IsPrimitive && !IsGhost && TypeAsTBD.IsValueType;
}
2003-04-14 13:41:58 +04:00
}
2005-06-01 13:49:30 +04:00
internal bool IsPrimitive
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name == null;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsWidePrimitive
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return this == PrimitiveTypeWrapper.LONG || this == PrimitiveTypeWrapper.DOUBLE;
}
2003-11-17 15:01:50 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsIntOnStackPrimitive
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return name == null &&
(this == PrimitiveTypeWrapper.BOOLEAN ||
this == PrimitiveTypeWrapper.BYTE ||
this == PrimitiveTypeWrapper.CHAR ||
this == PrimitiveTypeWrapper.SHORT ||
this == PrimitiveTypeWrapper.INT);
}
2003-11-17 15:01:50 +03:00
}
2006-10-19 10:12:48 +04:00
private static bool IsJavaPrimitive(Type type)
{
return type == PrimitiveTypeWrapper.BOOLEAN.TypeAsTBD
|| type == PrimitiveTypeWrapper.BYTE.TypeAsTBD
|| type == PrimitiveTypeWrapper.CHAR.TypeAsTBD
|| type == PrimitiveTypeWrapper.DOUBLE.TypeAsTBD
|| type == PrimitiveTypeWrapper.FLOAT.TypeAsTBD
|| type == PrimitiveTypeWrapper.INT.TypeAsTBD
|| type == PrimitiveTypeWrapper.LONG.TypeAsTBD
|| type == PrimitiveTypeWrapper.SHORT.TypeAsTBD
|| type == PrimitiveTypeWrapper.VOID.TypeAsTBD;
}
internal bool IsBoxedPrimitive
{
get
{
return !IsPrimitive && IsJavaPrimitive(TypeAsSignatureType);
}
}
2006-10-04 13:03:18 +04:00
internal bool IsErasedOrBoxedPrimitiveOrRemapped
2006-08-26 17:00:50 +04:00
{
get
{
bool erased = IsUnloadable || IsGhostArray;
return erased || IsBoxedPrimitive || (IsRemapped && this is DotNetTypeWrapper);
2006-08-26 17:00:50 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal bool IsUnloadable
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// NOTE we abuse modifiers to note unloadable classes
return modifiers == UnloadableModifiersHack;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsVerifierType
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// NOTE we abuse modifiers to note verifier types
return modifiers == VerifierTypeModifiersHack;
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal virtual bool IsMapUnsafeException
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return false;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal Modifiers Modifiers
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return modifiers;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
// since for inner classes, the modifiers returned by Class.getModifiers are different from the actual
// modifiers (as used by the VM access control mechanism), we have this additional property
internal virtual Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return modifiers;
}
2003-05-30 16:08:59 +04:00
}
2006-04-05 12:18:58 +04:00
internal bool IsInternal
{
get
{
return (flags & TypeFlags.InternalAccess) != 0;
}
set
{
// TODO do we need locking here?
if(value)
{
flags |= TypeFlags.InternalAccess;
}
else
{
flags &= ~TypeFlags.InternalAccess;
}
}
}
2005-06-01 13:49:30 +04:00
internal bool IsPublic
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return (modifiers & Modifiers.Public) != 0;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsAbstract
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// interfaces don't need to marked abstract explicitly (and javac 1.1 didn't do it)
return (modifiers & (Modifiers.Abstract | Modifiers.Interface)) != 0;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsFinal
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return (modifiers & Modifiers.Final) != 0;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal bool IsInterface
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
Debug.Assert(!IsUnloadable && !IsVerifierType);
return (modifiers & Modifiers.Interface) != 0;
}
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
// this exists because interfaces and arrays of interfaces are treated specially
// by the verifier, interfaces don't have a common base (other than java.lang.Object)
// so any object reference or object array reference can be used where an interface
// or interface array reference is expected (the compiler will insert the required casts).
internal bool IsInterfaceOrInterfaceArray
2003-08-29 14:14:08 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-29 14:14:08 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper tw = this;
while(tw.IsArray)
{
tw = tw.ElementTypeWrapper;
}
return tw.IsInterface;
2003-08-29 14:14:08 +04:00
}
}
2006-03-23 14:57:41 +03:00
internal abstract ClassLoaderWrapper GetClassLoader();
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal FieldWrapper GetFieldWrapper(string fieldName, string fieldSig)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
lock(this)
{
if(fields == null)
{
LazyPublishMembers();
}
}
foreach(FieldWrapper fw in fields)
{
if(fw.Name == fieldName && fw.Signature == fieldSig)
{
return fw;
}
}
foreach(TypeWrapper iface in this.Interfaces)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
FieldWrapper fw = iface.GetFieldWrapper(fieldName, fieldSig);
if(fw != null)
{
return fw;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
if(baseWrapper != null)
{
return baseWrapper.GetFieldWrapper(fieldName, fieldSig);
}
return null;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
protected virtual void LazyPublishMembers()
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if(methods == null)
{
methods = MethodWrapper.EmptyArray;
}
if(fields == null)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
fields = FieldWrapper.EmptyArray;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal MethodWrapper[] GetMethods()
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock(this)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if(methods == null)
{
LazyPublishMembers();
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
return methods;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal FieldWrapper[] GetFields()
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock(this)
{
if(fields == null)
{
LazyPublishMembers();
}
}
return fields;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal MethodWrapper GetMethodWrapper(string name, string sig, bool inherit)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
lock(this)
{
if(methods == null)
{
LazyPublishMembers();
}
}
2006-05-03 12:52:52 +04:00
// MemberWrapper interns the name and sig so we can use ref equality
// profiling has shown this to be more efficient
string _name = String.IsInterned(name);
string _sig = String.IsInterned(sig);
2005-06-01 13:49:30 +04:00
foreach(MethodWrapper mw in methods)
{
2006-05-03 12:52:52 +04:00
// NOTE we can use ref equality, because names and signatures are
// always interned by MemberWrapper
if(ReferenceEquals(mw.Name, _name) && ReferenceEquals(mw.Signature, _sig))
2005-06-01 13:49:30 +04:00
{
return mw;
}
}
if(inherit && baseWrapper != null)
{
return baseWrapper.GetMethodWrapper(name, sig, inherit);
}
return null;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal void SetMethods(MethodWrapper[] methods)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(methods != null);
this.methods = methods;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal void SetFields(FieldWrapper[] fields)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(fields != null);
this.fields = fields;
2005-01-03 11:26:21 +03:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal string Name
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
return name;
2005-01-03 11:26:21 +03:00
}
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// the name of the type as it appears in a Java signature string (e.g. "Ljava.lang.Object;" or "I")
internal virtual string SigName
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
return "L" + this.Name + ";";
2005-01-03 11:26:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
// returns true iff wrapper is allowed to access us
internal bool IsAccessibleFrom(TypeWrapper wrapper)
2005-01-03 11:26:21 +03:00
{
2006-04-05 12:18:58 +04:00
return IsPublic
|| (IsInternal && GetClassLoader().InternalsVisibleTo(wrapper.GetClassLoader()))
|| IsPackageAccessibleFrom(wrapper);
2002-12-18 19:00:25 +03:00
}
internal bool IsPackageAccessibleFrom(TypeWrapper wrapper)
2002-12-18 19:00:25 +03:00
{
if(GetClassLoader().InternalsVisibleTo(wrapper.GetClassLoader()))
2005-06-01 13:49:30 +04:00
{
int index1 = name.LastIndexOf('.');
int index2 = wrapper.name.LastIndexOf('.');
if(index1 == -1 && index2 == -1)
{
return true;
}
// for array types we need to skip the brackets
int skip1 = 0;
int skip2 = 0;
while(name[skip1] == '[')
{
skip1++;
}
while(wrapper.name[skip2] == '[')
{
skip2++;
}
if(skip1 > 0)
{
// skip over the L that follows the brackets
skip1++;
}
if(skip2 > 0)
{
// skip over the L that follows the brackets
skip2++;
}
if((index1 - skip1) != (index2 - skip2))
{
return false;
}
return String.CompareOrdinal(name, skip1, wrapper.name, skip2, index1 - skip1) == 0;
}
return false;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal abstract Type TypeAsTBD
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get;
2003-08-21 14:06:34 +04:00
}
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
internal virtual TypeBuilder TypeAsBuilder
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
TypeBuilder typeBuilder = TypeAsTBD as TypeBuilder;
Debug.Assert(typeBuilder != null);
return typeBuilder;
2002-12-18 19:00:25 +03:00
}
}
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal Type TypeAsSignatureType
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
if(IsUnloadable)
{
return typeof(object);
}
if(IsGhostArray)
{
2006-07-05 12:46:56 +04:00
return ArrayTypeWrapper.MakeArrayType(typeof(object), ArrayRank);
2005-06-01 13:49:30 +04:00
}
return TypeAsTBD;
}
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
internal virtual Type TypeAsBaseType
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
return TypeAsTBD;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
}
internal Type TypeAsLocalOrStackType
{
get
2003-08-12 17:09:31 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE as a convenience to the compiler, we replace return address types with typeof(int)
if(VerifierTypeWrapper.IsRet(this))
{
return typeof(int);
}
if(IsUnloadable || IsGhost)
{
return typeof(object);
}
if(IsNonPrimitiveValueType)
{
// return either System.ValueType or System.Enum
return TypeAsTBD.BaseType;
}
if(IsGhostArray)
2003-08-12 17:09:31 +04:00
{
2006-07-05 12:46:56 +04:00
return ArrayTypeWrapper.MakeArrayType(typeof(object), ArrayRank);
2003-08-12 17:09:31 +04:00
}
2005-06-01 13:49:30 +04:00
return TypeAsTBD;
2003-08-12 17:09:31 +04:00
}
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
/** <summary>Use this if the type is used as an array or array element</summary> */
internal Type TypeAsArrayType
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
if(IsUnloadable || IsGhost)
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
return typeof(object);
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
if(IsGhostArray)
{
2006-07-05 12:46:56 +04:00
return ArrayTypeWrapper.MakeArrayType(typeof(object), ArrayRank);
2005-06-01 13:49:30 +04:00
}
return TypeAsTBD;
2003-09-10 18:58:19 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal Type TypeAsExceptionType
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if(IsUnloadable)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
return typeof(Exception);
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
return TypeAsTBD;
2003-10-17 12:08:31 +04:00
}
2003-09-10 18:58:19 +04:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper BaseTypeWrapper
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
return baseWrapper;
2003-09-10 18:58:19 +04:00
}
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
internal TypeWrapper ElementTypeWrapper
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
Debug.Assert(!this.IsUnloadable);
Debug.Assert(this == VerifierTypeWrapper.Null || this.IsArray);
if(this == VerifierTypeWrapper.Null)
{
return VerifierTypeWrapper.Null;
}
// TODO consider caching the element type
switch(name[1])
{
case '[':
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
// (because the ultimate element type was already loaded when this type was created)
2006-03-23 14:57:41 +03:00
return GetClassLoader().LoadClassByDottedNameFast(name.Substring(1));
2005-06-01 13:49:30 +04:00
case 'L':
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
// (because the ultimate element type was already loaded when this type was created)
2006-03-23 14:57:41 +03:00
return GetClassLoader().LoadClassByDottedNameFast(name.Substring(2, name.Length - 3));
2005-06-01 13:49:30 +04:00
case 'Z':
return PrimitiveTypeWrapper.BOOLEAN;
case 'B':
return PrimitiveTypeWrapper.BYTE;
case 'S':
return PrimitiveTypeWrapper.SHORT;
case 'C':
return PrimitiveTypeWrapper.CHAR;
case 'I':
return PrimitiveTypeWrapper.INT;
case 'J':
return PrimitiveTypeWrapper.LONG;
case 'F':
return PrimitiveTypeWrapper.FLOAT;
case 'D':
return PrimitiveTypeWrapper.DOUBLE;
default:
throw new InvalidOperationException(name);
}
}
2002-12-18 19:00:25 +03:00
}
2006-07-21 14:18:13 +04:00
internal TypeWrapper MakeArrayType(int rank)
2003-01-06 16:56:37 +03:00
{
2005-08-19 13:08:43 +04:00
Debug.Assert(rank != 0);
2005-06-01 13:49:30 +04:00
// NOTE this call to LoadClassByDottedNameFast can never fail and will not trigger a class load
return GetClassLoader().LoadClassByDottedNameFast(new String('[', rank) + this.SigName);
}
2003-12-24 14:51:41 +03:00
2005-06-01 13:49:30 +04:00
internal bool ImplementsInterface(TypeWrapper interfaceWrapper)
{
TypeWrapper typeWrapper = this;
while(typeWrapper != null)
2003-06-13 19:13:20 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper[] interfaces = typeWrapper.Interfaces;
for(int i = 0; i < interfaces.Length; i++)
{
if(interfaces[i] == interfaceWrapper)
{
return true;
}
if(interfaces[i].ImplementsInterface(interfaceWrapper))
{
return true;
}
}
typeWrapper = typeWrapper.BaseTypeWrapper;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
return false;
2003-01-06 16:56:37 +03:00
}
2003-12-24 14:51:41 +03:00
2005-06-01 13:49:30 +04:00
internal bool IsSubTypeOf(TypeWrapper baseType)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// make sure IsSubTypeOf isn't used on primitives
Debug.Assert(!this.IsPrimitive);
Debug.Assert(!baseType.IsPrimitive);
// can't be used on Unloadable
Debug.Assert(!this.IsUnloadable);
Debug.Assert(!baseType.IsUnloadable);
if(baseType.IsInterface)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if(baseType == this)
2002-12-18 19:00:25 +03:00
{
return true;
}
2005-06-01 13:49:30 +04:00
return ImplementsInterface(baseType);
}
// NOTE this isn't just an optimization, it is also required when this is an interface
if(baseType == CoreClasses.java.lang.Object.Wrapper)
{
return true;
}
TypeWrapper subType = this;
while(subType != baseType)
{
subType = subType.BaseTypeWrapper;
if(subType == null)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return false;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
return true;
2002-12-18 19:00:25 +03:00
}
2003-01-07 17:53:17 +03:00
2005-06-01 13:49:30 +04:00
internal bool IsAssignableTo(TypeWrapper wrapper)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if(this == wrapper)
2002-12-18 19:00:25 +03:00
{
return true;
}
2005-06-01 13:49:30 +04:00
if(this.IsPrimitive || wrapper.IsPrimitive)
2002-12-18 19:00:25 +03:00
{
return false;
}
2005-06-01 13:49:30 +04:00
if(this == VerifierTypeWrapper.Null)
{
return true;
}
if(wrapper.IsInterface)
{
return ImplementsInterface(wrapper);
}
int rank1 = this.ArrayRank;
int rank2 = wrapper.ArrayRank;
if(rank1 > 0 && rank2 > 0)
{
rank1--;
rank2--;
TypeWrapper elem1 = this.ElementTypeWrapper;
TypeWrapper elem2 = wrapper.ElementTypeWrapper;
while(rank1 != 0 && rank2 != 0)
{
elem1 = elem1.ElementTypeWrapper;
elem2 = elem2.ElementTypeWrapper;
rank1--;
rank2--;
}
return (!elem1.IsNonPrimitiveValueType && elem1.IsSubTypeOf(elem2)) || (rank1 == rank2 && elem2.IsGhost && elem1 == CoreClasses.java.lang.Object.Wrapper);
2005-06-01 13:49:30 +04:00
}
return this.IsSubTypeOf(wrapper);
2002-12-18 19:00:25 +03:00
}
internal bool IsInstance(object obj)
{
2007-05-31 12:20:04 +04:00
#if !FIRST_PASS && !STATIC_COMPILER
if(obj != null)
{
TypeWrapper thisWrapper = this;
TypeWrapper objWrapper = IKVM.NativeCode.ikvm.runtime.Util.GetTypeWrapperFromObject(obj);
if(thisWrapper.IsGhostArray)
{
TypeWrapper elementType = objWrapper;
while(elementType.IsArray)
{
elementType = elementType.ElementTypeWrapper;
}
return thisWrapper.ArrayRank == objWrapper.ArrayRank && elementType == CoreClasses.java.lang.Object.Wrapper;
}
return objWrapper.IsAssignableTo(thisWrapper);
}
2007-05-31 12:20:04 +04:00
#endif
return false;
}
2005-06-01 13:49:30 +04:00
internal abstract TypeWrapper[] Interfaces
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE this property can only be called for finished types!
internal abstract TypeWrapper[] InnerClasses
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get;
2003-01-06 16:56:37 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE this property can only be called for finished types!
internal abstract TypeWrapper DeclaringTypeWrapper
2004-02-02 12:46:13 +03:00
{
2005-06-01 13:49:30 +04:00
get;
2004-02-02 12:46:13 +03:00
}
2005-06-01 13:49:30 +04:00
2005-08-05 12:40:54 +04:00
internal abstract void Finish();
2004-08-17 13:05:21 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-06-01 13:49:30 +04:00
private void ImplementInterfaceMethodStubImpl(MethodWrapper ifmethod, TypeBuilder typeBuilder, DynamicTypeWrapper wrapper)
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
// we're mangling the name to prevent subclasses from accidentally overriding this method and to
// prevent clashes with overloaded method stubs that are erased to the same signature (e.g. unloadable types and ghost arrays)
2006-11-01 11:55:25 +03:00
// HACK the signature and name are the wrong way around to work around a C++/CLI bug (apparantely it looks looks at the last n
// characters of the method name, or something bizarre like that)
// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=234167
string mangledName = this.Name + "/" + ifmethod.Signature + ifmethod.Name;
2005-06-01 13:49:30 +04:00
MethodWrapper mce = null;
TypeWrapper lookup = wrapper;
while(lookup != null)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
mce = lookup.GetMethodWrapper(ifmethod.Name, ifmethod.Signature, true);
if(mce == null || !mce.IsStatic)
{
break;
}
lookup = mce.DeclaringType.BaseTypeWrapper;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
if(mce != null)
2002-12-18 19:00:25 +03:00
{
Debug.Assert(!mce.HasCallerID);
2005-08-02 12:44:55 +04:00
if(mce.DeclaringType != wrapper)
{
// check the loader constraints
bool error = false;
if(mce.ReturnType != ifmethod.ReturnType)
{
// TODO handle unloadable
error = true;
}
TypeWrapper[] mceparams = mce.GetParameters();
TypeWrapper[] ifparams = ifmethod.GetParameters();
for(int i = 0; i < mceparams.Length; i++)
{
if(mceparams[i] != ifparams[i])
{
// TODO handle unloadable
error = true;
break;
}
}
if(error)
{
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder.DefineMethod(mangledName, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, ifmethod.ReturnTypeForDefineMethod, ifmethod.GetParametersForDefineMethod());
2005-08-02 12:44:55 +04:00
AttributeHelper.HideFromJava(mb);
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.LinkageError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
2005-08-02 12:44:55 +04:00
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
return;
}
}
2005-06-01 13:49:30 +04:00
if(mce.IsMirandaMethod && mce.DeclaringType == wrapper)
{
// Miranda methods already have a methodimpl (if needed) to implement the correct interface method
}
else if(!mce.IsPublic)
{
// NOTE according to the ECMA spec it isn't legal for a privatescope method to be virtual, but this works and
// it makes sense, so I hope the spec is wrong
// UPDATE unfortunately, according to Serge Lidin the spec is correct, and it is not allowed to have virtual privatescope
// methods. Sigh! So I have to use private methods and mangle the name
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder.DefineMethod(mangledName, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, ifmethod.ReturnTypeForDefineMethod, ifmethod.GetParametersForDefineMethod());
2005-06-01 13:49:30 +04:00
AttributeHelper.HideFromJava(mb);
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.IllegalAccessError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
2005-06-01 13:49:30 +04:00
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
wrapper.HasIncompleteInterfaceImplementation = true;
}
else if(mce.GetMethod() == null || mce.RealName != ifmethod.RealName)
{
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder.DefineMethod(mangledName, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, ifmethod.ReturnTypeForDefineMethod, ifmethod.GetParametersForDefineMethod());
2005-06-01 13:49:30 +04:00
AttributeHelper.HideFromJava(mb);
CodeEmitter ilGenerator = CodeEmitter.Create(mb);
2005-06-01 13:49:30 +04:00
ilGenerator.Emit(OpCodes.Ldarg_0);
int argc = mce.GetParameters().Length;
for(int n = 0; n < argc; n++)
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(n + 1));
}
mce.EmitCallvirt(ilGenerator);
ilGenerator.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
}
2007-10-10 10:54:20 +04:00
else if(!mce.DeclaringType.TypeAsTBD.Assembly.Equals(typeBuilder.Assembly))
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
// NOTE methods inherited from base classes in a different assembly do *not* automatically implement
// interface methods, so we have to generate a stub here that doesn't do anything but call the base
// implementation
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder.DefineMethod(mangledName, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, ifmethod.ReturnTypeForDefineMethod, ifmethod.GetParametersForDefineMethod());
2005-06-01 13:49:30 +04:00
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
AttributeHelper.HideFromJava(mb);
CodeEmitter ilGenerator = CodeEmitter.Create(mb);
2005-06-01 13:49:30 +04:00
ilGenerator.Emit(OpCodes.Ldarg_0);
int argc = mce.GetParameters().Length;
for(int n = 0; n < argc; n++)
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(n + 1));
}
mce.EmitCallvirt(ilGenerator);
ilGenerator.Emit(OpCodes.Ret);
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
else
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
if(!wrapper.IsAbstract)
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
// the type doesn't implement the interface method and isn't abstract either. The JVM allows this, but the CLR doesn't,
// so we have to create a stub method that throws an AbstractMethodError
2005-09-01 11:34:53 +04:00
MethodBuilder mb = typeBuilder.DefineMethod(mangledName, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final, ifmethod.ReturnTypeForDefineMethod, ifmethod.GetParametersForDefineMethod());
2005-06-01 13:49:30 +04:00
AttributeHelper.HideFromJava(mb);
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.AbstractMethodError", wrapper.Name + "." + ifmethod.Name + ifmethod.Signature);
2005-06-01 13:49:30 +04:00
typeBuilder.DefineMethodOverride(mb, (MethodInfo)ifmethod.GetMethod());
wrapper.HasIncompleteInterfaceImplementation = true;
2002-12-29 19:27:00 +03:00
}
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal void ImplementInterfaceMethodStubs(TypeBuilder typeBuilder, DynamicTypeWrapper wrapper, Hashtable doneSet)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(this.IsInterface);
2006-08-26 17:00:50 +04:00
// make sure we don't do the same method twice and dynamic only interfaces
// don't really exist, so there is no point in generating stub methods for
// them (nor can we).
if(doneSet.ContainsKey(this))
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
return;
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
doneSet.Add(this, this);
foreach(MethodWrapper method in GetMethods())
{
if(!method.IsStatic && !method.IsDynamicOnly)
2005-06-01 13:49:30 +04:00
{
ImplementInterfaceMethodStubImpl(method, typeBuilder, wrapper);
}
}
TypeWrapper[] interfaces = Interfaces;
for(int i = 0; i < interfaces.Length; i++)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
interfaces[i].ImplementInterfaceMethodStubs(typeBuilder, wrapper, doneSet);
2002-12-18 19:00:25 +03:00
}
}
2005-12-07 12:06:32 +03:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
[Conditional("DEBUG")]
internal static void AssertFinished(Type type)
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
if(type != null)
2003-02-22 15:28:12 +03:00
{
2007-01-16 13:14:47 +03:00
while(type.HasElementType)
2005-06-01 13:49:30 +04:00
{
type = type.GetElementType();
}
Debug.Assert(!(type is TypeBuilder));
2003-02-22 15:28:12 +03:00
}
}
2003-12-20 01:19:18 +03:00
2005-06-01 13:49:30 +04:00
internal void RunClassInit()
2005-02-02 18:11:26 +03:00
{
Type t = IsRemapped ? TypeAsBaseType : TypeAsTBD;
2006-06-15 16:29:11 +04:00
if(t != null)
{
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(t.TypeHandle);
}
2005-02-02 18:11:26 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal void EmitUnbox(CodeEmitter ilgen)
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(this.IsNonPrimitiveValueType);
2005-12-19 18:12:49 +03:00
ilgen.LazyEmitUnboxSpecial(this.TypeAsTBD);
2005-02-02 18:11:26 +03:00
}
2005-06-01 13:49:30 +04:00
internal void EmitBox(CodeEmitter ilgen)
2005-02-02 18:11:26 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(this.IsNonPrimitiveValueType);
2005-12-19 18:12:49 +03:00
ilgen.LazyEmitBox(this.TypeAsTBD);
2005-02-02 18:11:26 +03:00
}
internal void EmitConvSignatureTypeToStackType(CodeEmitter ilgen)
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
if(IsUnloadable)
2003-12-20 01:19:18 +03:00
{
}
2005-06-01 13:49:30 +04:00
else if(this == PrimitiveTypeWrapper.BYTE)
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen.Emit(OpCodes.Conv_I1);
2004-03-08 18:18:47 +03:00
}
else if(IsNonPrimitiveValueType)
{
2005-06-01 13:49:30 +04:00
EmitBox(ilgen);
}
else if(IsGhost)
{
LocalBuilder local = ilgen.DeclareLocal(TypeAsSignatureType);
ilgen.Emit(OpCodes.Stloc, local);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldfld, GhostRefField);
2004-03-08 18:18:47 +03:00
}
2003-12-20 01:19:18 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE sourceType is optional and only used for interfaces,
// it is *not* used to automatically downcast
internal void EmitConvStackTypeToSignatureType(CodeEmitter ilgen, TypeWrapper sourceType)
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if(!IsUnloadable)
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if(IsGhost)
{
LocalBuilder local1 = ilgen.DeclareLocal(TypeAsLocalOrStackType);
ilgen.Emit(OpCodes.Stloc, local1);
LocalBuilder local2 = ilgen.DeclareLocal(TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local2);
ilgen.Emit(OpCodes.Ldloc, local1);
ilgen.Emit(OpCodes.Stfld, GhostRefField);
ilgen.Emit(OpCodes.Ldloca, local2);
ilgen.Emit(OpCodes.Ldobj, TypeAsSignatureType);
}
// because of the way interface merging works, any reference is valid
// for any interface reference
else if(IsInterfaceOrInterfaceArray && (sourceType == null || sourceType.IsUnloadable || !sourceType.IsAssignableTo(this)))
{
EmitHelper.EmitAssertType(ilgen, TypeAsTBD);
Profiler.Count("InterfaceDownCast");
}
else if(IsNonPrimitiveValueType)
{
EmitUnbox(ilgen);
}
2005-08-05 16:18:35 +04:00
else if(sourceType != null && sourceType.IsUnloadable)
{
ilgen.Emit(OpCodes.Castclass, TypeAsSignatureType);
}
2004-01-11 16:14:42 +03:00
}
}
internal virtual void EmitCheckcast(TypeWrapper context, CodeEmitter ilgen)
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if(IsGhost)
{
ilgen.Emit(OpCodes.Dup);
// TODO make sure we get the right "Cast" method and cache it
// NOTE for dynamic ghosts we don't end up here because AotTypeWrapper overrides this method,
2005-06-01 13:49:30 +04:00
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
ilgen.Emit(OpCodes.Call, TypeAsTBD.GetMethod("Cast"));
ilgen.Emit(OpCodes.Pop);
}
else if(IsGhostArray)
{
ilgen.Emit(OpCodes.Dup);
// TODO make sure we get the right "CastArray" method and cache it
// NOTE for dynamic ghosts we don't end up here because AotTypeWrapper overrides this method,
2005-06-01 13:49:30 +04:00
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
TypeWrapper tw = this;
int rank = 0;
while(tw.IsArray)
{
rank++;
tw = tw.ElementTypeWrapper;
}
ilgen.Emit(OpCodes.Ldc_I4, rank);
ilgen.Emit(OpCodes.Call, tw.TypeAsTBD.GetMethod("CastArray"));
ilgen.Emit(OpCodes.Castclass, ArrayTypeWrapper.MakeArrayType(typeof(object), rank));
2005-06-01 13:49:30 +04:00
}
else
{
EmitHelper.Castclass(ilgen, TypeAsTBD);
}
2004-01-11 16:14:42 +03:00
}
2005-06-01 13:49:30 +04:00
internal virtual void EmitInstanceOf(TypeWrapper context, CodeEmitter ilgen)
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
if(IsGhost)
{
// TODO make sure we get the right "IsInstance" method and cache it
// NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
ilgen.Emit(OpCodes.Call, TypeAsTBD.GetMethod("IsInstance"));
}
else if(IsGhostArray)
{
// TODO make sure we get the right "IsInstanceArray" method and cache it
// NOTE for dynamic ghosts we don't end up here because DynamicTypeWrapper overrides this method,
// so we're safe to call GetMethod on TypeAsTBD (because it has to be a compiled type, if we're here)
2006-06-08 13:26:33 +04:00
TypeWrapper tw = this;
int rank = 0;
while(tw.IsArray)
{
rank++;
tw = tw.ElementTypeWrapper;
}
ilgen.Emit(OpCodes.Ldc_I4, rank);
ilgen.Emit(OpCodes.Call, tw.TypeAsTBD.GetMethod("IsInstanceArray"));
2005-06-01 13:49:30 +04:00
}
else
{
2006-11-27 10:39:30 +03:00
ilgen.LazyEmit_instanceof(TypeAsTBD);
2005-06-01 13:49:30 +04:00
}
2004-01-11 16:14:42 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
// NOTE don't call this method, call MethodWrapper.Link instead
internal virtual MethodBase LinkMethod(MethodWrapper mw)
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
return mw.GetMethod();
2004-01-11 16:14:42 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE don't call this method, call FieldWrapper.Link instead
internal virtual FieldInfo LinkField(FieldWrapper fw)
2004-01-11 16:14:42 +03:00
{
2005-06-01 13:49:30 +04:00
return fw.GetField();
2004-01-11 16:14:42 +03:00
}
2005-08-24 12:14:23 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal virtual void EmitRunClassConstructor(CodeEmitter ilgen)
2005-08-24 12:14:23 +04:00
{
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal abstract string GetGenericSignature();
internal abstract string GetGenericMethodSignature(MethodWrapper mw);
internal abstract string GetGenericFieldSignature(FieldWrapper fw);
internal abstract string[] GetEnclosingMethod();
2005-11-01 17:01:42 +03:00
internal virtual object[] GetDeclaredAnnotations()
{
return null;
}
2006-04-19 19:49:54 +04:00
internal virtual object[] GetMethodAnnotations(MethodWrapper mw)
{
return null;
}
internal virtual object[][] GetParameterAnnotations(MethodWrapper mw)
{
return null;
}
internal virtual object[] GetFieldAnnotations(FieldWrapper fw)
{
return null;
}
2006-05-04 12:09:56 +04:00
internal virtual string GetSourceFileName()
{
return null;
}
internal virtual int GetSourceLineNumber(MethodBase mb, int ilOffset)
{
return -1;
}
2006-04-10 13:09:09 +04:00
#if !STATIC_COMPILER
2005-11-01 17:01:42 +03:00
internal virtual object GetAnnotationDefault(MethodWrapper mw)
{
MethodBase mb = mw.GetMethod();
if(mb != null)
{
if(mb.DeclaringType.Assembly.ReflectionOnly)
{
// TODO
return null;
}
2005-11-01 17:01:42 +03:00
object[] attr = mb.GetCustomAttributes(typeof(AnnotationDefaultAttribute), false);
if(attr.Length == 1)
{
return JVM.NewAnnotationElementValue(mw.DeclaringType.GetClassLoader().GetJavaClassLoader(), mw.ReturnType.ClassObject, ((AnnotationDefaultAttribute)attr[0]).Value);
2005-11-01 17:01:42 +03:00
}
}
return null;
}
#endif // !STATIC_COMPILER
2005-11-01 17:01:42 +03:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
internal virtual Annotation Annotation
{
get
{
return null;
}
}
2006-12-28 10:46:21 +03:00
internal virtual Type EnumType
{
get
{
return null;
}
}
2005-12-07 12:06:32 +03:00
#endif
2004-01-11 16:14:42 +03:00
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
class UnloadableTypeWrapper : TypeWrapper
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
internal UnloadableTypeWrapper(string name)
2006-03-23 14:57:41 +03:00
: base(TypeWrapper.UnloadableModifiersHack, name, null)
2005-06-01 13:49:30 +04:00
{
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if(name != "<verifier>")
2005-06-01 13:49:30 +04:00
{
if(name.StartsWith("["))
{
int skip = 1;
while(name[skip++] == '[');
name = name.Substring(skip, name.Length - skip - 1);
}
2006-07-26 18:16:52 +04:00
StaticCompiler.IssueMessage(Message.ClassNotFound, name);
2005-06-01 13:49:30 +04:00
}
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
}
2005-02-23 15:56:15 +03:00
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader()
{
return null;
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper EnsureLoadable(ClassLoaderWrapper loader)
2005-02-23 15:56:15 +03:00
{
2005-08-25 11:46:57 +04:00
TypeWrapper tw = loader.LoadClassByDottedNameFast(this.Name);
2005-06-01 13:49:30 +04:00
if(tw == null)
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
throw new NoClassDefFoundError(this.Name);
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
return tw;
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
internal override string SigName
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
string name = Name;
if(name.StartsWith("["))
{
return name;
}
return "L" + name + ";";
}
2005-02-23 15:56:15 +03:00
}
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers()
2005-02-23 15:56:15 +03:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException("LazyPublishMembers called on UnloadableTypeWrapper: " + Name);
2005-02-23 15:56:15 +03:00
}
2003-01-06 16:56:37 +03:00
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException("get_Type called on UnloadableTypeWrapper: " + Name);
2006-10-04 13:03:18 +04:00
}
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] Interfaces
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException("get_Interfaces called on UnloadableTypeWrapper: " + Name);
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] InnerClasses
{
get
{
throw new InvalidOperationException("get_InnerClasses called on UnloadableTypeWrapper: " + Name);
}
}
2003-01-06 16:56:37 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
throw new InvalidOperationException("get_DeclaringTypeWrapper called on UnloadableTypeWrapper: " + Name);
}
}
2003-01-06 16:56:37 +03:00
2005-08-05 12:40:54 +04:00
internal override void Finish()
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException("Finish called on UnloadableTypeWrapper: " + Name);
2003-01-06 16:56:37 +03:00
}
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal override void EmitCheckcast(TypeWrapper context, CodeEmitter ilgen)
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen.Emit(OpCodes.Ldtoken, context.TypeAsTBD);
ilgen.Emit(OpCodes.Ldstr, Name);
2006-04-11 16:05:24 +04:00
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicCast);
2003-02-18 12:30:34 +03:00
}
internal override void EmitInstanceOf(TypeWrapper context, CodeEmitter ilgen)
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen.Emit(OpCodes.Ldtoken, context.TypeAsTBD);
ilgen.Emit(OpCodes.Ldstr, Name);
2006-04-11 16:05:24 +04:00
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.DynamicInstanceOf);
2003-02-18 12:30:34 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature()
{
throw new InvalidOperationException("GetGenericSignature called on UnloadableTypeWrapper: " + Name);
}
internal override string GetGenericMethodSignature(MethodWrapper mw)
{
throw new InvalidOperationException("GetGenericMethodSignature called on UnloadableTypeWrapper: " + Name);
}
internal override string GetGenericFieldSignature(FieldWrapper fw)
{
throw new InvalidOperationException("GetGenericFieldSignature called on UnloadableTypeWrapper: " + Name);
}
internal override string[] GetEnclosingMethod()
{
throw new InvalidOperationException("GetEnclosingMethod called on UnloadableTypeWrapper: " + Name);
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
class PrimitiveTypeWrapper : TypeWrapper
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper(typeof(byte), "B");
internal static readonly PrimitiveTypeWrapper CHAR = new PrimitiveTypeWrapper(typeof(char), "C");
internal static readonly PrimitiveTypeWrapper DOUBLE = new PrimitiveTypeWrapper(typeof(double), "D");
internal static readonly PrimitiveTypeWrapper FLOAT = new PrimitiveTypeWrapper(typeof(float), "F");
internal static readonly PrimitiveTypeWrapper INT = new PrimitiveTypeWrapper(typeof(int), "I");
internal static readonly PrimitiveTypeWrapper LONG = new PrimitiveTypeWrapper(typeof(long), "J");
internal static readonly PrimitiveTypeWrapper SHORT = new PrimitiveTypeWrapper(typeof(short), "S");
internal static readonly PrimitiveTypeWrapper BOOLEAN = new PrimitiveTypeWrapper(typeof(bool), "Z");
internal static readonly PrimitiveTypeWrapper VOID = new PrimitiveTypeWrapper(typeof(void), "V");
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
private readonly Type type;
private readonly string sigName;
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
private PrimitiveTypeWrapper(Type type, string sigName)
2006-03-23 14:57:41 +03:00
: base(Modifiers.Public | Modifiers.Abstract | Modifiers.Final, null, null)
2005-06-01 13:49:30 +04:00
{
this.type = type;
this.sigName = sigName;
}
2003-01-06 16:56:37 +03:00
internal static bool IsPrimitiveType(Type type)
{
return type == BYTE.type
|| type == CHAR.type
|| type == DOUBLE.type
|| type == FLOAT.type
|| type == INT.type
|| type == LONG.type
|| type == SHORT.type
|| type == BOOLEAN.type
|| type == VOID.type;
}
2005-06-01 13:49:30 +04:00
internal override string SigName
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return sigName;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal override ClassLoaderWrapper GetClassLoader()
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper.GetBootstrapClassLoader();
2003-08-21 14:06:34 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
{
get
{
return type;
}
}
2003-04-14 13:41:58 +04:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper.EmptyArray;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] InnerClasses
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper.EmptyArray;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return null;
}
2003-02-18 12:30:34 +03:00
}
2005-08-05 12:40:54 +04:00
internal override void Finish()
2003-02-18 12:30:34 +03:00
{
}
2005-06-01 13:49:30 +04:00
public override string ToString()
{
return "PrimitiveTypeWrapper[" + sigName + "]";
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature()
{
return null;
}
internal override string GetGenericMethodSignature(MethodWrapper mw)
{
return null;
}
internal override string GetGenericFieldSignature(FieldWrapper fw)
{
return null;
}
internal override string[] GetEnclosingMethod()
{
return null;
}
2002-12-18 19:00:25 +03:00
}
2005-02-02 18:11:26 +03:00
#if !COMPACT_FRAMEWORK
2008-06-03 11:13:49 +04:00
static class BakedTypeCleanupHack
{
private static readonly FieldInfo m_methodBuilder = typeof(ConstructorBuilder).GetField("m_methodBuilder", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo[] methodBuilderFields = GetFieldList(typeof(MethodBuilder), new string[]
{
"m_ilGenerator",
"m_ubBody",
"m_RVAFixups",
"mm_mdMethodFixups",
"m_localSignature",
"m_localSymInfo",
"m_exceptions",
"m_parameterTypes",
"m_retParam",
"m_returnType",
"m_signature"
});
private static readonly FieldInfo[] fieldBuilderFields = GetFieldList(typeof(FieldBuilder), new string[]
{
"m_data",
"m_fieldType",
});
private static bool IsSupportedVersion
{
get
{
return Environment.Version.Major == 2 && Environment.Version.Minor == 0 && Environment.Version.Build == 50727 && Environment.Version.Revision == 1433;
}
}
private static FieldInfo[] GetFieldList(Type type, string[] list)
{
if(JVM.SafeGetEnvironmentVariable("IKVM_DISABLE_TYPEBUILDER_HACK") != null || !IsSupportedVersion)
{
return null;
}
if(!SecurityManager.IsGranted(new SecurityPermission(SecurityPermissionFlag.Assertion)) ||
!SecurityManager.IsGranted(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)))
{
return null;
}
FieldInfo[] fields = new FieldInfo[list.Length];
for(int i = 0; i < list.Length; i++)
{
fields[i] = type.GetField(list[i], BindingFlags.Instance | BindingFlags.NonPublic);
if(fields[i] == null)
{
return null;
}
}
return fields;
}
internal static void Process(DynamicTypeWrapper wrapper)
{
if(m_methodBuilder != null && methodBuilderFields != null && fieldBuilderFields != null)
{
foreach(MethodWrapper mw in wrapper.GetMethods())
{
MethodBuilder mb = mw.GetMethod() as MethodBuilder;
if(mb == null)
{
ConstructorBuilder cb = mw.GetMethod() as ConstructorBuilder;
if(cb != null)
{
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
mb = (MethodBuilder)m_methodBuilder.GetValue(cb);
CodeAccessPermission.RevertAssert();
}
}
if(mb != null)
{
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
foreach(FieldInfo fi in methodBuilderFields)
{
fi.SetValue(mb, null);
}
CodeAccessPermission.RevertAssert();
}
}
foreach(FieldWrapper fw in wrapper.GetFields())
{
FieldBuilder fb = fw.GetField() as FieldBuilder;
if(fb != null)
{
new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
foreach(FieldInfo fi in fieldBuilderFields)
{
fi.SetValue(fb, null);
}
CodeAccessPermission.RevertAssert();
}
}
}
}
}
#endif
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2006-09-12 13:57:36 +04:00
#if STATIC_COMPILER
abstract class DynamicTypeWrapper : TypeWrapper
#else
2005-06-01 13:49:30 +04:00
class DynamicTypeWrapper : TypeWrapper
2006-09-12 13:57:36 +04:00
#endif
2004-08-17 13:05:21 +04:00
{
2006-07-06 17:53:51 +04:00
protected readonly ClassLoaderWrapper classLoader;
2005-06-01 13:49:30 +04:00
private volatile DynamicImpl impl;
private TypeWrapper[] interfaces;
2006-05-04 12:09:56 +04:00
private readonly string sourceFileName;
2006-08-17 17:18:45 +04:00
#if !STATIC_COMPILER
2006-05-04 12:09:56 +04:00
private byte[][] lineNumberTables;
2006-08-17 17:18:45 +04:00
#endif
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
private static TypeWrapper LoadTypeWrapper(ClassLoaderWrapper classLoader, string name)
2003-01-06 16:56:37 +03:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper tw = classLoader.LoadClassByDottedNameFast(name);
if(tw == null)
2003-06-10 17:28:47 +04:00
{
2005-06-01 13:49:30 +04:00
throw new NoClassDefFoundError(name);
2003-06-10 17:28:47 +04:00
}
2005-06-01 13:49:30 +04:00
return tw;
}
2006-07-06 17:53:51 +04:00
internal DynamicTypeWrapper(ClassFile f, ClassLoaderWrapper classLoader)
2006-03-23 14:57:41 +03:00
: base(f.Modifiers, f.Name, f.IsInterface ? null : LoadTypeWrapper(classLoader, f.SuperClass))
2005-06-01 13:49:30 +04:00
{
Profiler.Count("DynamicTypeWrapper");
2006-03-23 14:57:41 +03:00
this.classLoader = classLoader;
2006-04-05 12:18:58 +04:00
this.IsInternal = f.IsInternal;
2006-05-04 12:09:56 +04:00
this.sourceFileName = f.SourceFileAttribute;
2005-06-01 13:49:30 +04:00
if(BaseTypeWrapper != null)
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
if(!BaseTypeWrapper.IsAccessibleFrom(this))
{
throw new IllegalAccessError("Class " + f.Name + " cannot access its superclass " + BaseTypeWrapper.Name);
}
2007-10-10 10:54:20 +04:00
if(!BaseTypeWrapper.IsPublic && !BaseTypeWrapper.TypeAsBaseType.Assembly.Equals(classLoader.GetTypeWrapperFactory().ModuleBuilder.Assembly))
{
// NOTE this can only happen if evil code calls ClassLoader.defineClass() on an assembly class loader (which we allow for compatibility with other slightly less evil code)
throw new IllegalAccessError("Class " + f.Name + " cannot access its non-public superclass " + BaseTypeWrapper.Name + " from another assembly");
}
2005-06-01 13:49:30 +04:00
if(BaseTypeWrapper.IsFinal)
{
2005-07-27 19:57:55 +04:00
throw new VerifyError("Class " + f.Name + " extends final class " + BaseTypeWrapper.Name);
2005-06-01 13:49:30 +04:00
}
if(BaseTypeWrapper.IsInterface)
{
throw new IncompatibleClassChangeError("Class " + f.Name + " has interface " + BaseTypeWrapper.Name + " as superclass");
}
if(!f.IsFinal)
{
if(BaseTypeWrapper.TypeAsTBD == typeof(ValueType) || BaseTypeWrapper.TypeAsTBD == typeof(Enum))
{
throw new VerifyError("Value types must be final");
}
if(BaseTypeWrapper.TypeAsTBD == typeof(MulticastDelegate))
{
throw new VerifyError("Delegates must be final");
}
}
if(BaseTypeWrapper.TypeAsTBD == typeof(Delegate))
{
throw new VerifyError(BaseTypeWrapper.Name + " cannot be used as a base class");
}
// NOTE defining value types, enums and delegates is not supported in IKVM v1
2004-10-04 23:30:53 +04:00
if(BaseTypeWrapper.TypeAsTBD == typeof(ValueType) || BaseTypeWrapper.TypeAsTBD == typeof(Enum))
{
2005-06-01 13:49:30 +04:00
throw new VerifyError("Defining value types in Java is not implemented in IKVM v1");
2004-10-04 23:30:53 +04:00
}
if(BaseTypeWrapper.TypeAsTBD == typeof(MulticastDelegate))
{
2005-06-01 13:49:30 +04:00
throw new VerifyError("Defining delegates in Java is not implemented in IKVM v1");
2004-10-04 23:30:53 +04:00
}
}
2005-06-01 13:49:30 +04:00
ClassFile.ConstantPoolItemClass[] interfaces = f.Interfaces;
this.interfaces = new TypeWrapper[interfaces.Length];
for(int i = 0; i < interfaces.Length; i++)
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper iface = LoadTypeWrapper(classLoader, interfaces[i].Name);
if(!iface.IsAccessibleFrom(this))
{
throw new IllegalAccessError("Class " + f.Name + " cannot access its superinterface " + iface.Name);
}
if(!iface.IsPublic
2007-10-10 10:54:20 +04:00
&& !iface.TypeAsBaseType.Assembly.Equals(classLoader.GetTypeWrapperFactory().ModuleBuilder.Assembly)
&& iface.TypeAsBaseType.Assembly.GetType(DynamicClassLoader.GetProxyHelperName(iface.TypeAsTBD)) == null)
{
// NOTE this happens when you call Proxy.newProxyInstance() on a non-public .NET interface
// (for ikvmc compiled Java types, ikvmc generates public proxy stubs).
// NOTE we don't currently check interfaces inherited from other interfaces because mainstream .NET languages
// don't allow public interfaces extending non-public interfaces.
throw new IllegalAccessError("Class " + f.Name + " cannot access its non-public superinterface " + iface.Name + " from another assembly");
}
2005-06-01 13:49:30 +04:00
if(!iface.IsInterface)
{
throw new IncompatibleClassChangeError("Implementing class");
}
this.interfaces[i] = iface;
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
impl = new JavaTypeImpl(f, this);
2003-01-06 16:56:37 +03:00
}
2004-08-17 13:05:21 +04:00
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader()
{
return classLoader;
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl.ReflectiveModifiers;
}
2003-05-30 16:08:59 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return interfaces;
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] InnerClasses
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl.InnerClasses;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl.DeclaringTypeWrapper;
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return impl.Type;
}
2002-12-18 19:00:25 +03:00
}
2006-12-28 10:46:21 +03:00
#if STATIC_COMPILER
internal override Annotation Annotation
{
get
{
return impl.Annotation;
}
}
internal override Type EnumType
{
get
{
return impl.EnumType;
}
}
#endif // STATIC_COMPILER
2005-08-05 12:40:54 +04:00
internal override void Finish()
2003-01-02 16:46:16 +03:00
{
2006-05-05 15:21:15 +04:00
// we don't need locking, because Finish is Thread safe
impl = impl.Finish();
2005-06-01 13:49:30 +04:00
}
// NOTE can only be used if the type hasn't been finished yet!
protected string GenerateUniqueMethodName(string basename, MethodWrapper mw)
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
return ((JavaTypeImpl)impl).GenerateUniqueMethodName(basename, mw);
2004-03-08 18:18:47 +03:00
}
2004-09-17 13:32:06 +04:00
// NOTE can only be used if the type hasn't been finished yet!
internal string GenerateUniqueMethodName(string basename, Type returnType, Type[] parameterTypes)
{
return ((JavaTypeImpl)impl).GenerateUniqueMethodName(basename, returnType, parameterTypes);
}
2006-05-05 15:21:15 +04:00
internal void CreateStep1(out bool hasclinit)
{
((JavaTypeImpl)impl).CreateStep1(out hasclinit);
}
internal void CreateStep2NoFail(bool hasclinit, string mangledTypeName)
{
((JavaTypeImpl)impl).CreateStep2NoFail(hasclinit, mangledTypeName);
}
2005-06-01 13:49:30 +04:00
private abstract class DynamicImpl
{
internal abstract Type Type { get; }
internal abstract TypeWrapper[] InnerClasses { get; }
internal abstract TypeWrapper DeclaringTypeWrapper { get; }
internal abstract Modifiers ReflectiveModifiers { get; }
2006-12-28 10:46:21 +03:00
#if STATIC_COMPILER
internal abstract Annotation Annotation { get; }
internal abstract Type EnumType { get; }
#endif
2005-08-05 12:40:54 +04:00
internal abstract DynamicImpl Finish();
2005-06-01 13:49:30 +04:00
internal abstract MethodBase LinkMethod(MethodWrapper mw);
internal abstract FieldInfo LinkField(FieldWrapper fw);
internal abstract void EmitRunClassConstructor(CodeEmitter ilgen);
2005-10-01 15:16:11 +04:00
internal abstract string GetGenericSignature();
internal abstract string[] GetEnclosingMethod();
internal abstract string GetGenericMethodSignature(int index);
internal abstract string GetGenericFieldSignature(int index);
2005-11-01 17:01:42 +03:00
internal abstract object[] GetDeclaredAnnotations();
internal abstract object GetMethodDefaultValue(int index);
2006-04-19 19:49:54 +04:00
internal abstract object[] GetMethodAnnotations(int index);
internal abstract object[][] GetParameterAnnotations(int index);
internal abstract object[] GetFieldAnnotations(int index);
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
2006-05-15 13:08:01 +04:00
private sealed class JavaTypeImpl : DynamicImpl
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly ClassFile classFile;
private readonly DynamicTypeWrapper wrapper;
2006-05-05 15:21:15 +04:00
private TypeBuilder typeBuilder;
2005-06-01 13:49:30 +04:00
private MethodWrapper[] methods;
private MethodWrapper[] baseMethods;
private FieldWrapper[] fields;
private FinishedTypeImpl finishedType;
private bool finishInProgress;
2005-06-01 13:49:30 +04:00
private Hashtable memberclashtable;
2006-05-06 14:46:51 +04:00
private Hashtable classCache = Hashtable.Synchronized(new Hashtable());
2005-08-24 12:14:23 +04:00
private MethodBuilder clinitMethod;
private MethodBuilder finalizeMethod;
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
2006-05-15 13:08:01 +04:00
private DynamicTypeWrapper outerClassWrapper;
2005-11-01 17:01:42 +03:00
private AnnotationBuilder annotationBuilder;
2006-12-28 10:46:21 +03:00
private TypeBuilder enumBuilder;
2006-04-10 13:09:09 +04:00
#endif
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal JavaTypeImpl(ClassFile f, DynamicTypeWrapper wrapper)
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Tracer.Info(Tracer.Compiler, "constructing JavaTypeImpl for " + f.Name);
this.classFile = f;
this.wrapper = wrapper;
2006-05-05 15:21:15 +04:00
}
2005-06-01 13:49:30 +04:00
2006-05-05 15:21:15 +04:00
internal void CreateStep1(out bool hasclinit)
{
2005-06-01 13:49:30 +04:00
// process all methods
2006-05-05 15:21:15 +04:00
hasclinit = wrapper.BaseTypeWrapper == null ? false : wrapper.BaseTypeWrapper.HasStaticInitializer;
2005-06-01 13:49:30 +04:00
methods = new MethodWrapper[classFile.Methods.Length];
baseMethods = new MethodWrapper[classFile.Methods.Length];
for(int i = 0; i < methods.Length; i++)
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
ClassFile.Method m = classFile.Methods[i];
if(m.IsClassInitializer)
2004-09-15 17:35:44 +04:00
{
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if(!IsSideEffectFreeStaticInitializer(m))
2004-09-15 17:35:44 +04:00
{
hasclinit = true;
}
2006-04-10 13:09:09 +04:00
#else
hasclinit = true;
#endif
2004-09-15 17:35:44 +04:00
}
2006-04-05 12:18:58 +04:00
MemberFlags flags = MemberFlags.None;
if(m.IsInternal)
{
flags |= MemberFlags.InternalAccess;
}
// we only support HasCallerID instance methods on final types, because we don't support interface stubs with CallerID
if(m.HasCallerIDAnnotation
&& (m.IsStatic || classFile.IsFinal)
&& wrapper.GetClassLoader() == CoreClasses.java.lang.Object.Wrapper.GetClassLoader())
{
flags |= MemberFlags.CallerID;
}
2005-06-01 13:49:30 +04:00
if(wrapper.IsGhost)
{
2006-04-05 12:18:58 +04:00
methods[i] = new MethodWrapper.GhostMethodWrapper(wrapper, m.Name, m.Signature, null, null, null, m.Modifiers, flags);
2005-06-01 13:49:30 +04:00
}
else if(ReferenceEquals(m.Name, StringConstants.INIT) || m.IsClassInitializer)
2005-06-01 13:49:30 +04:00
{
2006-04-05 12:18:58 +04:00
methods[i] = new SmartConstructorMethodWrapper(wrapper, m.Name, m.Signature, null, null, m.Modifiers, flags);
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
else
{
2005-06-01 13:49:30 +04:00
if(!classFile.IsInterface && !m.IsStatic && !m.IsPrivate)
{
2006-04-05 12:18:58 +04:00
bool explicitOverride = false;
2005-06-01 13:49:30 +04:00
baseMethods[i] = FindBaseMethod(m.Name, m.Signature, out explicitOverride);
2006-04-05 12:18:58 +04:00
if(explicitOverride)
{
flags |= MemberFlags.ExplicitOverride;
}
2005-06-01 13:49:30 +04:00
}
2006-04-05 12:18:58 +04:00
methods[i] = new SmartCallMethodWrapper(wrapper, m.Name, m.Signature, null, null, null, m.Modifiers, flags, SimpleOpCode.Call, SimpleOpCode.Callvirt);
2004-09-15 17:35:44 +04:00
}
}
2006-04-05 12:18:58 +04:00
wrapper.HasStaticInitializer = hasclinit;
if(!wrapper.IsInterface || wrapper.IsPublic)
2003-02-20 17:18:38 +03:00
{
2005-08-14 19:49:50 +04:00
ArrayList methodsArray = null;
ArrayList baseMethodsArray = null;
if(wrapper.IsAbstract)
{
methodsArray = new ArrayList(methods);
baseMethodsArray = new ArrayList(baseMethods);
AddMirandaMethods(methodsArray, baseMethodsArray, wrapper);
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if(!wrapper.IsInterface && wrapper.IsPublic)
2005-08-14 19:49:50 +04:00
{
TypeWrapper baseTypeWrapper = wrapper.BaseTypeWrapper;
while(baseTypeWrapper != null && !baseTypeWrapper.IsPublic)
{
if(methodsArray == null)
{
methodsArray = new ArrayList(methods);
baseMethodsArray = new ArrayList(baseMethods);
}
AddAccessStubMethods(methodsArray, baseMethodsArray, baseTypeWrapper);
baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper;
}
}
2006-04-10 13:09:09 +04:00
#endif
2005-08-14 19:49:50 +04:00
if(methodsArray != null)
{
this.methods = (MethodWrapper[])methodsArray.ToArray(typeof(MethodWrapper));
this.baseMethods = (MethodWrapper[])baseMethodsArray.ToArray(typeof(MethodWrapper));
}
2003-02-20 17:18:38 +03:00
}
2005-06-01 13:49:30 +04:00
wrapper.SetMethods(methods);
fields = new FieldWrapper[classFile.Fields.Length];
for(int i = 0; i < fields.Length; i++)
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
ClassFile.Field fld = classFile.Fields[i];
if(fld.IsStatic && fld.IsFinal && fld.ConstantValue != null)
2004-08-17 13:05:21 +04:00
{
2006-10-10 20:24:48 +04:00
TypeWrapper fieldType = null;
#if !STATIC_COMPILER
fieldType = ClassLoaderWrapper.GetBootstrapClassLoader().FieldTypeWrapperFromSig(fld.Signature);
#endif
fields[i] = new ConstantFieldWrapper(wrapper, fieldType, fld.Name, fld.Signature, fld.Modifiers, null, fld.ConstantValue, MemberFlags.None);
2005-06-01 13:49:30 +04:00
}
else if(fld.IsProperty)
{
fields[i] = new DynamicPropertyFieldWrapper(wrapper, fld);
}
#if STATIC_COMPILER && !OPENJDK
2006-09-12 13:57:36 +04:00
else if(fld.IsFinal
&& (fld.IsPublic || fld.IsProtected)
&& wrapper.IsPublic
&& !wrapper.IsInterface
&& (!wrapper.classLoader.StrictFinalFieldSemantics || wrapper.Name == "java.lang.System"))
2005-06-01 13:49:30 +04:00
{
2006-08-15 12:50:43 +04:00
fields[i] = new GetterFieldWrapper(wrapper, null, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal), null, null);
2005-06-01 13:49:30 +04:00
}
2006-09-12 13:57:36 +04:00
#endif
2005-06-01 13:49:30 +04:00
else
{
2006-04-05 12:18:58 +04:00
fields[i] = FieldWrapper.Create(wrapper, null, null, fld.Name, fld.Signature, new ExModifiers(fld.Modifiers, fld.IsInternal));
2004-08-17 13:05:21 +04:00
}
2005-01-03 11:26:21 +03:00
}
2006-04-10 13:09:09 +04:00
#if STATIC_COMPILER
if(wrapper.IsPublic)
2005-08-14 19:49:50 +04:00
{
ArrayList fieldsArray = new ArrayList(fields);
AddAccessStubFields(fieldsArray, wrapper);
fields = (FieldWrapper[])fieldsArray.ToArray(typeof(FieldWrapper));
}
((AotTypeWrapper)wrapper).AddMapXmlFields(ref fields);
2006-04-10 13:09:09 +04:00
#endif
2005-06-01 13:49:30 +04:00
wrapper.SetFields(fields);
2006-05-05 15:21:15 +04:00
}
2004-08-17 13:05:21 +04:00
2006-05-05 15:21:15 +04:00
internal void CreateStep2NoFail(bool hasclinit, string mangledTypeName)
{
2006-05-15 13:08:01 +04:00
// this method is not allowed to throw exceptions (if it does, the runtime will abort)
2006-05-05 15:21:15 +04:00
ClassFile f = classFile;
2005-06-01 13:49:30 +04:00
try
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
TypeAttributes typeAttribs = 0;
if(f.IsAbstract)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs |= TypeAttributes.Abstract;
}
if(f.IsFinal)
{
typeAttribs |= TypeAttributes.Sealed;
}
if(!hasclinit)
{
typeAttribs |= TypeAttributes.BeforeFieldInit;
}
2006-05-15 13:08:01 +04:00
#if STATIC_COMPILER
bool cantNest = false;
2006-10-09 16:32:33 +04:00
bool setModifiers = false;
2005-06-01 13:49:30 +04:00
TypeBuilder outer = null;
2006-05-15 13:08:01 +04:00
// we only compile inner classes as nested types in the static compiler, because it has a higher cost
// and doesn't buy us anything in dynamic mode (and if fact, due to an FXBUG it would make handling
// the TypeResolve event very hard)
ClassFile.InnerClass outerClass = getOuterClass();
if(outerClass.outerClass != 0)
2005-06-01 13:49:30 +04:00
{
2006-05-15 13:08:01 +04:00
string outerClassName = classFile.GetConstantPoolClass(outerClass.outerClass);
if(!CheckInnerOuterNames(f.Name, outerClassName))
2004-08-17 13:05:21 +04:00
{
2006-05-15 13:08:01 +04:00
Tracer.Warning(Tracer.Compiler, "Incorrect InnerClasses attribute on {0}", f.Name);
}
else
{
try
2005-06-01 13:49:30 +04:00
{
2006-05-15 13:08:01 +04:00
outerClassWrapper = wrapper.GetClassLoader().LoadClassByDottedNameFast(outerClassName) as DynamicTypeWrapper;
2005-06-01 13:49:30 +04:00
}
2006-05-15 13:08:01 +04:00
catch(RetargetableJavaException x)
2004-08-17 13:05:21 +04:00
{
2006-10-27 20:55:07 +04:00
Tracer.Warning(Tracer.Compiler, "Unable to load outer class {0} for inner class {1} ({2}: {3})", outerClassName, f.Name, x.GetType().Name, x.Message);
2006-05-15 13:08:01 +04:00
}
if(outerClassWrapper != null)
{
// make sure the relationship is reciprocal (otherwise we run the risk of
// baking the outer type before the inner type)
if(outerClassWrapper.impl is JavaTypeImpl)
2005-08-03 16:59:16 +04:00
{
2006-05-15 13:08:01 +04:00
ClassFile outerClassFile = ((JavaTypeImpl)outerClassWrapper.impl).classFile;
ClassFile.InnerClass[] outerInnerClasses = outerClassFile.InnerClasses;
if(outerInnerClasses == null)
2005-08-03 16:59:16 +04:00
{
2006-05-15 13:08:01 +04:00
outerClassWrapper = null;
}
else
{
bool ok = false;
for(int i = 0; i < outerInnerClasses.Length; i++)
2005-08-03 16:59:16 +04:00
{
2006-05-15 13:08:01 +04:00
if(outerInnerClasses[i].outerClass != 0
&& outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name
&& outerInnerClasses[i].innerClass != 0
&& outerClassFile.GetConstantPoolClass(outerInnerClasses[i].innerClass) == f.Name)
2005-08-03 16:59:16 +04:00
{
2006-05-15 13:08:01 +04:00
ok = true;
break;
2005-08-03 16:59:16 +04:00
}
}
2006-05-15 13:08:01 +04:00
if(!ok)
2005-08-03 16:59:16 +04:00
{
outerClassWrapper = null;
}
}
2006-05-15 13:08:01 +04:00
}
else
{
outerClassWrapper = null;
}
if(outerClassWrapper != null)
{
outer = outerClassWrapper.TypeAsBuilder;
}
else
{
Tracer.Warning(Tracer.Compiler, "Non-reciprocal inner class {0}", f.Name);
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
}
2003-10-17 12:08:31 +04:00
}
2006-04-05 12:18:58 +04:00
if(f.IsPublic)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if(outer != null)
{
if(outerClassWrapper.IsPublic)
{
typeAttribs |= TypeAttributes.NestedPublic;
}
else
{
// We're a public type nested inside a non-public type, this means that we can't compile this type as a nested type,
// because that would mean it wouldn't be visible outside the assembly.
cantNest = true;
typeAttribs |= TypeAttributes.Public;
}
2005-06-01 13:49:30 +04:00
}
else
{
typeAttribs |= TypeAttributes.Public;
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
else if(outer != null)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs |= TypeAttributes.NestedAssembly;
2003-10-17 12:08:31 +04:00
}
2006-05-15 13:08:01 +04:00
#else // STATIC_COMPILER
if(f.IsPublic)
{
typeAttribs |= TypeAttributes.Public;
}
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
if(f.IsInterface)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
typeAttribs |= TypeAttributes.Interface | TypeAttributes.Abstract;
2006-05-15 13:08:01 +04:00
#if STATIC_COMPILER
if(outer != null && !cantNest)
2005-06-01 13:49:30 +04:00
{
if(wrapper.IsGhost)
{
// TODO this is low priority, since the current Java class library doesn't define any ghost interfaces
// as inner classes
throw new NotImplementedException();
}
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
// (and broken by J# as well), so we'll just ignore it too.
typeBuilder = outer.DefineNestedType(GetInnerClassName(outerClassWrapper.Name, f.Name), typeAttribs);
}
else
2004-08-17 13:05:21 +04:00
{
2006-09-12 13:57:36 +04:00
if(wrapper.IsGhost)
{
typeBuilder = wrapper.DefineGhostType(mangledTypeName, typeAttribs);
}
else
{
typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs);
}
2004-08-17 13:05:21 +04:00
}
2006-09-12 13:57:36 +04:00
#else // STATIC_COMPILER
typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs);
#endif // STATIC_COMPILER
2004-08-17 13:05:21 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
typeAttribs |= TypeAttributes.Class;
2006-05-15 13:08:01 +04:00
#if STATIC_COMPILER
2006-10-09 16:32:33 +04:00
if(f.IsEffectivelyFinal)
{
if(outer == null)
{
setModifiers = true;
}
else
{
// we don't need a ModifiersAttribute, because the InnerClassAttribute already records
// the modifiers
}
typeAttribs |= TypeAttributes.Sealed;
Tracer.Info(Tracer.Compiler, "Sealing type {0}", f.Name);
}
if(outer != null && !cantNest)
2005-06-01 13:49:30 +04:00
{
// LAMESPEC the CLI spec says interfaces cannot contain nested types (Part.II, 9.6), but that rule isn't enforced
// (and broken by J# as well), so we'll just ignore it too.
typeBuilder = outer.DefineNestedType(GetInnerClassName(outerClassWrapper.Name, f.Name), typeAttribs, wrapper.BaseTypeWrapper.TypeAsBaseType);
}
else
2006-05-15 13:08:01 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
{
2006-07-26 18:16:52 +04:00
typeBuilder = wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(mangledTypeName, typeAttribs, wrapper.BaseTypeWrapper.TypeAsBaseType);
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
2006-07-24 12:21:11 +04:00
#if STATIC_COMPILER
if(outer != null && cantNest)
{
AttributeHelper.SetNonNestedOuterClass(typeBuilder, outerClassWrapper.Name);
AttributeHelper.SetNonNestedInnerClass(outer, f.Name);
}
2006-07-24 12:21:11 +04:00
if(outer == null && mangledTypeName != wrapper.Name)
{
// HACK we abuse the InnerClassAttribute to record to real name
AttributeHelper.SetInnerClass(typeBuilder, wrapper.Name, wrapper.Modifiers);
2006-08-14 11:57:03 +04:00
}
if(typeBuilder.FullName != wrapper.Name
&& wrapper.Name.Replace('$', '+') != typeBuilder.FullName)
{
((CompilerClassLoader)wrapper.GetClassLoader()).AddNameMapping(wrapper.Name, typeBuilder.FullName);
2006-07-24 12:21:11 +04:00
}
2006-05-15 13:08:01 +04:00
string annotationAttributeType = null;
if(f.IsAnnotation && Annotation.HasRetentionPolicyRuntime(f.Annotations))
{
annotationBuilder = new AnnotationBuilder(this);
((AotTypeWrapper)wrapper).SetAnnotation(annotationBuilder);
annotationAttributeType = annotationBuilder.AttributeTypeName;
}
2006-12-28 10:46:21 +03:00
// For Java 5 Enum types, we generate a nested .NET enum.
// This is primarily to support annotations that take enum parameters.
if(f.IsEnum && f.IsPublic)
{
// TODO make sure there isn't already a nested type with the __Enum name
enumBuilder = wrapper.TypeAsBuilder.DefineNestedType("__Enum", TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPublic | TypeAttributes.Serializable, typeof(Enum));
AttributeHelper.HideFromJava(enumBuilder);
enumBuilder.DefineField("value__", typeof(int), FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
for(int i = 0; i < f.Fields.Length; i++)
{
if(f.Fields[i].IsEnum)
{
FieldBuilder fieldBuilder = enumBuilder.DefineField(f.Fields[i].Name, enumBuilder, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
fieldBuilder.SetConstant(i);
}
}
}
TypeWrapper[] interfaces = wrapper.Interfaces;
2006-05-15 13:08:01 +04:00
string[] implements = new string[interfaces.Length];
for(int i = 0; i < implements.Length; i++)
{
implements[i] = interfaces[i].Name;
}
2006-08-17 17:18:45 +04:00
if(outer != null)
2006-05-15 13:08:01 +04:00
{
2006-08-17 17:18:45 +04:00
Modifiers innerClassModifiers = outerClass.accessFlags;
string innerClassName = classFile.GetConstantPoolClass(outerClass.innerClass);
if(innerClassName == classFile.Name && innerClassName == outerClassWrapper.Name + "$" + typeBuilder.Name)
2006-05-15 13:08:01 +04:00
{
2006-08-17 17:18:45 +04:00
innerClassName = null;
2006-05-15 13:08:01 +04:00
}
2006-08-17 17:18:45 +04:00
AttributeHelper.SetInnerClass(typeBuilder, innerClassName, innerClassModifiers);
2006-05-15 13:08:01 +04:00
}
2006-08-17 17:18:45 +04:00
else if(outerClass.innerClass != 0)
{
AttributeHelper.SetInnerClass(typeBuilder, null, outerClass.accessFlags);
}
2005-06-01 13:49:30 +04:00
AttributeHelper.SetImplementsAttribute(typeBuilder, interfaces);
2006-05-04 12:09:56 +04:00
if(classFile.DeprecatedAttribute)
2004-08-17 13:05:21 +04:00
{
2006-05-04 12:09:56 +04:00
AttributeHelper.SetDeprecatedAttribute(typeBuilder);
}
if(classFile.GenericSignature != null)
{
AttributeHelper.SetSignatureAttribute(typeBuilder, classFile.GenericSignature);
}
if(classFile.EnclosingMethod != null)
{
AttributeHelper.SetEnclosingMethodAttribute(typeBuilder, classFile.EnclosingMethod[0], classFile.EnclosingMethod[1], classFile.EnclosingMethod[2]);
2005-06-01 13:49:30 +04:00
}
2006-05-15 13:08:01 +04:00
if(annotationAttributeType != null)
{
CustomAttributeBuilder cab = new CustomAttributeBuilder(JVM.LoadType(typeof(AnnotationAttributeAttribute)).GetConstructor(new Type[] { typeof(string) }), new object[] { annotationAttributeType });
2006-05-15 13:08:01 +04:00
typeBuilder.SetCustomAttribute(cab);
}
2006-08-29 10:28:34 +04:00
if(wrapper.classLoader.EmitStackTraceInfo)
2005-06-01 13:49:30 +04:00
{
2005-07-07 15:24:08 +04:00
if(f.SourceFileAttribute != null)
{
if(f.SourceFileAttribute != typeBuilder.Name + ".java")
{
AttributeHelper.SetSourceFile(typeBuilder, f.SourceFileAttribute);
}
}
else
{
AttributeHelper.SetSourceFile(typeBuilder, null);
}
2004-08-17 13:05:21 +04:00
}
2006-05-15 13:08:01 +04:00
// NOTE in Whidbey we can (and should) use CompilerGeneratedAttribute to mark Synthetic types
2006-10-09 16:32:33 +04:00
if(setModifiers || classFile.IsInternal || (classFile.Modifiers & (Modifiers.Synthetic | Modifiers.Annotation | Modifiers.Enum)) != 0)
2006-05-15 13:08:01 +04:00
{
AttributeHelper.SetModifiers(typeBuilder, classFile.Modifiers, classFile.IsInternal);
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2007-11-26 14:01:29 +03:00
if(hasclinit)
2005-08-24 12:14:23 +04:00
{
// We create a empty method that we can use to trigger our .cctor
// (previously we used RuntimeHelpers.RunClassConstructor, but that is slow and requires additional privileges)
MethodAttributes attribs = MethodAttributes.Static | MethodAttributes.SpecialName;
if(classFile.IsAbstract)
{
bool hasfields = false;
// If we have any public static fields, the cctor trigger must (and may) be public as well
foreach(ClassFile.Field fld in classFile.Fields)
{
if(fld.IsPublic && fld.IsStatic)
{
hasfields = true;
break;
}
}
attribs |= hasfields ? MethodAttributes.Public : MethodAttributes.FamORAssem;
}
else
{
attribs |= MethodAttributes.Public;
}
clinitMethod = typeBuilder.DefineMethod("__<clinit>", attribs, null, null);
clinitMethod.GetILGenerator().Emit(OpCodes.Ret);
// FXBUG on .NET 2.0 RTM x64 the JIT sometimes throws an InvalidProgramException while trying to inline this method,
// so we prevent inlining for now (it also turns out that on x86 not inlining this method actually has a positive perf impact in some cases...)
// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=285772
clinitMethod.SetImplementationFlags(clinitMethod.GetMethodImplementationFlags() | MethodImplAttributes.NoInlining);
2005-08-24 12:14:23 +04:00
}
if(HasStructLayoutAttributeAnnotation(classFile))
{
// when we have a StructLayoutAttribute, field order is significant,
// so we link all fields here to make sure they are created in class file order.
foreach(FieldWrapper fw in fields)
{
fw.Link();
}
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
catch(Exception x)
2004-10-19 17:43:55 +04:00
{
2006-05-05 15:21:15 +04:00
JVM.CriticalFailure("Exception during JavaTypeImpl.CreateStep2NoFail", x);
2004-10-19 17:43:55 +04:00
}
2002-12-29 19:27:00 +03:00
}
2005-06-01 13:49:30 +04:00
private static bool HasStructLayoutAttributeAnnotation(ClassFile c)
{
if(c.Annotations != null)
{
foreach(object[] annot in c.Annotations)
{
if("Lcli/System/Runtime/InteropServices/StructLayoutAttribute$Annotation;".Equals(annot[1]))
{
return true;
}
}
}
return false;
}
#if STATIC_COMPILER
2006-05-15 13:08:01 +04:00
private ClassFile.InnerClass getOuterClass()
2005-08-03 16:59:16 +04:00
{
ClassFile.InnerClass[] innerClasses = classFile.InnerClasses;
if(innerClasses != null)
{
for(int j = 0; j < innerClasses.Length; j++)
{
2006-05-15 13:08:01 +04:00
if(innerClasses[j].innerClass != 0
2005-08-03 16:59:16 +04:00
&& classFile.GetConstantPoolClass(innerClasses[j].innerClass) == classFile.Name)
{
2006-05-15 13:08:01 +04:00
return innerClasses[j];
2005-08-03 16:59:16 +04:00
}
}
}
2006-05-15 13:08:01 +04:00
return new ClassFile.InnerClass();
2005-08-03 16:59:16 +04:00
}
2005-06-01 13:49:30 +04:00
private bool IsSideEffectFreeStaticInitializer(ClassFile.Method m)
2002-12-29 19:27:00 +03:00
{
2005-06-01 13:49:30 +04:00
if(m.ExceptionTable.Length != 0)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return false;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
for(int i = 0; i < m.Instructions.Length; i++)
2004-09-15 17:35:44 +04:00
{
2005-07-20 14:47:59 +04:00
NormalizedByteCode bc = m.Instructions[i].NormalizedOpCode;
if(bc == NormalizedByteCode.__getstatic || bc == NormalizedByteCode.__putstatic)
2005-06-01 13:49:30 +04:00
{
2006-06-22 14:04:07 +04:00
ClassFile.ConstantPoolItemFieldref fld = classFile.SafeGetFieldref(m.Instructions[i].Arg1);
if(fld == null || fld.Class != classFile.Name)
2005-06-01 13:49:30 +04:00
{
return false;
}
// don't allow getstatic to load non-primitive fields, because that would
// cause the verifier to try to load the type
2005-07-20 14:47:59 +04:00
if(bc == NormalizedByteCode.__getstatic && "L[".IndexOf(fld.Signature[0]) != -1)
2005-06-01 13:49:30 +04:00
{
return false;
}
}
2005-07-20 14:47:59 +04:00
else if(bc == NormalizedByteCode.__areturn ||
bc == NormalizedByteCode.__ireturn ||
bc == NormalizedByteCode.__lreturn ||
bc == NormalizedByteCode.__freturn ||
bc == NormalizedByteCode.__dreturn)
2004-09-15 17:35:44 +04:00
{
return false;
}
2005-06-01 13:49:30 +04:00
else if(ByteCodeMetaData.CanThrowException(bc))
2004-09-15 17:35:44 +04:00
{
return false;
}
2006-06-22 14:04:07 +04:00
else if(bc == NormalizedByteCode.__ldc
&& classFile.SafeIsConstantPoolClass(m.Instructions[i].Arg1))
{
return false;
}
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
// the method needs to be verifiable to be side effect free, since we already analysed it,
// we know that the verifier won't try to load any types (which isn't allowed at this time)
try
2004-09-15 17:35:44 +04:00
{
2006-08-29 10:28:34 +04:00
new MethodAnalyzer(wrapper, null, classFile, m, wrapper.classLoader);
2005-06-01 13:49:30 +04:00
return true;
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
catch(VerifyError)
2004-09-15 17:35:44 +04:00
{
return false;
}
}
2005-08-14 19:49:50 +04:00
private static bool ContainsMemberWrapper(ArrayList members, string name, string sig)
{
foreach(MemberWrapper mw in members)
{
if(mw.Name == name && mw.Signature == sig)
{
return true;
}
}
return false;
}
#endif // STATIC_COMPILER
2005-08-14 19:49:50 +04:00
2005-06-01 13:49:30 +04:00
private MethodWrapper GetMethodWrapperDuringCtor(TypeWrapper lookup, ArrayList methods, string name, string sig)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if(lookup == wrapper)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
foreach(MethodWrapper mw in methods)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if(mw.Name == name && mw.Signature == sig)
{
return mw;
}
}
if(lookup.BaseTypeWrapper == null)
{
return null;
}
else
{
return lookup.BaseTypeWrapper.GetMethodWrapper(name, sig, true);
2005-01-03 11:26:21 +03:00
}
}
else
{
2005-06-01 13:49:30 +04:00
return lookup.GetMethodWrapper(name, sig, true);
2005-01-03 11:26:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
private void AddMirandaMethods(ArrayList methods, ArrayList baseMethods, TypeWrapper tw)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
foreach(TypeWrapper iface in tw.Interfaces)
2004-08-17 13:05:21 +04:00
{
if(iface.IsPublic && this.wrapper.IsInterface)
{
// for interfaces, we only need miranda methods for non-public interfaces that we extend
continue;
}
2005-06-01 13:49:30 +04:00
AddMirandaMethods(methods, baseMethods, iface);
foreach(MethodWrapper ifmethod in iface.GetMethods())
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// skip <clinit>
if(!ifmethod.IsStatic)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper lookup = wrapper;
while(lookup != null)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper mw = GetMethodWrapperDuringCtor(lookup, methods, ifmethod.Name, ifmethod.Signature);
if(mw == null)
{
mw = new SmartCallMethodWrapper(wrapper, ifmethod.Name, ifmethod.Signature, null, null, null, Modifiers.Public | Modifiers.Abstract, MemberFlags.HideFromReflection | MemberFlags.MirandaMethod, SimpleOpCode.Call, SimpleOpCode.Callvirt);
methods.Add(mw);
baseMethods.Add(ifmethod);
break;
}
if(!mw.IsStatic)
{
break;
}
lookup = mw.DeclaringType.BaseTypeWrapper;
2004-08-17 13:05:21 +04:00
}
}
}
}
2003-11-17 15:01:50 +03:00
}
2003-02-20 17:18:38 +03:00
#if STATIC_COMPILER
2005-08-14 19:49:50 +04:00
private void AddAccessStubMethods(ArrayList methods, ArrayList baseMethods, TypeWrapper tw)
{
foreach(MethodWrapper mw in tw.GetMethods())
{
if((mw.IsPublic || mw.IsProtected)
&& mw.Name != "<init>"
&& !ContainsMemberWrapper(methods, mw.Name, mw.Signature))
{
MethodWrapper stub = new SmartCallMethodWrapper(wrapper, mw.Name, mw.Signature, null, null, null, mw.Modifiers, MemberFlags.HideFromReflection | MemberFlags.AccessStub, SimpleOpCode.Call, SimpleOpCode.Callvirt);
methods.Add(stub);
baseMethods.Add(mw);
}
}
}
private void AddAccessStubFields(ArrayList fields, TypeWrapper tw)
{
do
{
if(!tw.IsPublic)
{
foreach(FieldWrapper fw in tw.GetFields())
{
if((fw.IsPublic || fw.IsProtected)
&& !ContainsMemberWrapper(fields, fw.Name, fw.Signature))
{
fields.Add(new AotAccessStubFieldWrapper(wrapper, fw));
}
}
}
foreach(TypeWrapper iface in tw.Interfaces)
{
AddAccessStubFields(fields, iface);
}
tw = tw.BaseTypeWrapper;
} while(tw != null && !tw.IsPublic);
}
2005-06-01 13:49:30 +04:00
private static bool CheckInnerOuterNames(string inner, string outer)
{
// do some sanity checks on the inner/outer class names
2006-08-14 11:57:03 +04:00
return inner.Length > outer.Length + 1 && inner[outer.Length] == '$' && inner.StartsWith(outer);
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
private static string GetInnerClassName(string outer, string inner)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(CheckInnerOuterNames(inner, outer));
2006-08-14 11:57:03 +04:00
return DynamicClassLoader.EscapeName(inner.Substring(outer.Length + 1));
2003-11-17 15:01:50 +03:00
}
#endif // STATIC_COMPILER
2003-11-17 15:01:50 +03:00
2005-06-01 13:49:30 +04:00
private int GetMethodIndex(MethodWrapper mw)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
for(int i = 0; i < methods.Length; i++)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if(methods[i] == mw)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
return i;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException();
}
internal override MethodBase LinkMethod(MethodWrapper mw)
{
Debug.Assert(mw != null);
bool unloadableOverrideStub = false;
int index = GetMethodIndex(mw);
MethodWrapper baseMethod = baseMethods[index];
if(baseMethod != null)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
baseMethod.Link();
// check the loader constraints
if(mw.ReturnType != baseMethod.ReturnType)
2004-08-17 13:05:21 +04:00
{
2005-08-05 12:40:54 +04:00
if(baseMethod.ReturnType.IsUnloadable || JVM.FinishingForDebugSave)
2004-08-17 13:05:21 +04:00
{
2005-08-05 12:40:54 +04:00
if(!mw.ReturnType.IsUnloadable || (!baseMethod.ReturnType.IsUnloadable && JVM.FinishingForDebugSave))
2004-08-17 13:05:21 +04:00
{
unloadableOverrideStub = true;
}
}
else
{
#if STATIC_COMPILER
StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has a return type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has a return type \"{1}\"", mw.ReturnType, baseMethod.ReturnType, mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name);
#endif
2004-08-17 13:05:21 +04:00
throw new LinkageError("Loader constraints violated");
}
}
2005-06-01 13:49:30 +04:00
TypeWrapper[] here = mw.GetParameters();
TypeWrapper[] there = baseMethod.GetParameters();
for(int i = 0; i < here.Length; i++)
{
if(here[i] != there[i])
{
2005-08-05 12:40:54 +04:00
if(there[i].IsUnloadable || JVM.FinishingForDebugSave)
2005-06-01 13:49:30 +04:00
{
2005-08-05 12:40:54 +04:00
if(!here[i].IsUnloadable || (!there[i].IsUnloadable && JVM.FinishingForDebugSave))
2005-06-01 13:49:30 +04:00
{
unloadableOverrideStub = true;
}
}
else
{
#if STATIC_COMPILER
StaticCompiler.LinkageError("Method \"{2}.{3}{4}\" has an argument type \"{0}\" and tries to override method \"{5}.{3}{4}\" that has an argument type \"{1}\"", here[i], there[i], mw.DeclaringType.Name, mw.Name, mw.Signature, baseMethod.DeclaringType.Name);
#endif
2005-06-01 13:49:30 +04:00
throw new LinkageError("Loader constraints violated");
}
}
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
Debug.Assert(mw.GetMethod() == null);
MethodBase mb = GenerateMethod(index, unloadableOverrideStub);
if((mw.Modifiers & (Modifiers.Synchronized | Modifiers.Static)) == Modifiers.Synchronized)
{
// note that constructors cannot be synchronized in Java
MethodBuilder mbld = (MethodBuilder)mb;
mbld.SetImplementationFlags(mbld.GetMethodImplementationFlags() | MethodImplAttributes.Synchronized);
}
return mb;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private int GetFieldIndex(FieldWrapper fw)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
for(int i = 0; i < fields.Length; i++)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
if(fields[i] == fw)
{
return i;
}
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException();
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
internal override FieldInfo LinkField(FieldWrapper fw)
2005-01-03 11:26:21 +03:00
{
2005-08-14 19:49:50 +04:00
if(fw.IsAccessStub)
{
((AotAccessStubFieldWrapper)fw).DoLink(typeBuilder);
return null;
}
if(fw is DynamicPropertyFieldWrapper)
{
((DynamicPropertyFieldWrapper)fw).DoLink(typeBuilder);
return null;
}
int fieldIndex = GetFieldIndex(fw);
#if STATIC_COMPILER
if(fieldIndex >= classFile.Fields.Length)
{
// this must be a field defined in map.xml
FieldAttributes fieldAttribs = 0;
if(fw.IsPublic)
{
fieldAttribs |= FieldAttributes.Public;
}
else if(fw.IsProtected)
{
fieldAttribs |= FieldAttributes.FamORAssem;
}
else if(fw.IsPrivate)
{
fieldAttribs |= FieldAttributes.Private;
}
else
{
fieldAttribs |= FieldAttributes.Assembly;
}
if(fw.IsStatic)
{
fieldAttribs |= FieldAttributes.Static;
}
if(fw.IsFinal)
{
fieldAttribs |= FieldAttributes.InitOnly;
}
return typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType, fieldAttribs);
}
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
FieldBuilder field;
ClassFile.Field fld = classFile.Fields[fieldIndex];
2005-06-01 13:49:30 +04:00
string fieldName = fld.Name;
TypeWrapper typeWrapper = fw.FieldTypeWrapper;
Type type = typeWrapper.TypeAsSignatureType;
2006-10-04 13:03:18 +04:00
bool setNameSig = typeWrapper.IsErasedOrBoxedPrimitiveOrRemapped;
2005-06-01 13:49:30 +04:00
if(setNameSig)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO use clashtable
// the field name is mangled here, because otherwise it can (theoretically)
// conflict with another unloadable or object or ghost array field
// (fields can be overloaded on type)
fieldName += "/" + typeWrapper.Name;
}
FieldAttributes attribs = 0;
2005-09-01 11:34:53 +04:00
MethodAttributes methodAttribs = MethodAttributes.HideBySig;
2006-10-04 13:03:18 +04:00
#if STATIC_COMPILER
bool setModifiers = fld.IsInternal || (fld.Modifiers & (Modifiers.Synthetic | Modifiers.Enum)) != 0;
#endif
bool isWrappedFinal = false;
2005-06-01 13:49:30 +04:00
if(fld.IsPrivate)
{
attribs |= FieldAttributes.Private;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else if(fld.IsProtected)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs |= FieldAttributes.FamORAssem;
methodAttribs |= MethodAttributes.FamORAssem;
2005-01-03 11:26:21 +03:00
}
2006-04-05 12:18:58 +04:00
else if(fld.IsPublic)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs |= FieldAttributes.Public;
methodAttribs |= MethodAttributes.Public;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else
{
attribs |= FieldAttributes.Assembly;
methodAttribs |= MethodAttributes.Assembly;
}
if(fld.IsStatic)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
attribs |= FieldAttributes.Static;
methodAttribs |= MethodAttributes.Static;
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
// NOTE "constant" static finals are converted into literals
// TODO it would be possible for Java code to change the value of a non-blank static final, but I don't
// know if we want to support this (since the Java JITs don't really support it either)
object constantValue = fld.ConstantValue;
if(fld.IsStatic && fld.IsFinal && constantValue != null)
2005-01-03 11:26:21 +03:00
{
2005-06-01 13:49:30 +04:00
Profiler.Count("Static Final Constant");
attribs |= FieldAttributes.Literal;
field = typeBuilder.DefineField(fieldName, type, attribs);
field.SetConstant(constantValue);
2005-01-03 11:26:21 +03:00
}
2005-06-01 13:49:30 +04:00
else
2005-01-03 11:26:21 +03:00
{
2005-07-07 17:10:09 +04:00
if(fld.IsFinal)
2005-01-03 11:26:21 +03:00
{
2006-10-04 13:03:18 +04:00
isWrappedFinal = fw is GetterFieldWrapper;
2005-07-07 17:10:09 +04:00
if(isWrappedFinal)
2005-06-01 13:49:30 +04:00
{
// NOTE public/protected blank final fields get converted into a read-only property with a private field
// backing store
attribs &= ~FieldAttributes.FieldAccessMask;
2006-08-15 12:50:43 +04:00
attribs |= FieldAttributes.PrivateScope;
2005-06-01 13:49:30 +04:00
}
2006-08-29 10:28:34 +04:00
else if(wrapper.IsInterface || wrapper.classLoader.StrictFinalFieldSemantics)
2005-07-07 17:10:09 +04:00
{
attribs |= FieldAttributes.InitOnly;
}
else
{
2006-10-04 13:03:18 +04:00
#if STATIC_COMPILER
2005-07-07 17:10:09 +04:00
setModifiers = true;
2006-10-04 13:03:18 +04:00
#endif
2005-07-07 17:10:09 +04:00
}
2005-06-01 13:49:30 +04:00
}
2006-10-04 16:51:19 +04:00
Type[] modreq = Type.EmptyTypes;
if(fld.IsVolatile)
{
modreq = new Type[] { typeof(System.Runtime.CompilerServices.IsVolatile) };
}
2006-09-20 15:29:46 +04:00
// MONOBUG the __<> prefix for wrapped final fields is to work around a bug in mcs 1.1.17
// it crashes when it tries to lookup the property with the same name as the privatescope field
// http://bugzilla.ximian.com/show_bug.cgi?id=79451
field = typeBuilder.DefineField(isWrappedFinal ? "__<>" + fieldName : fieldName, type, modreq, Type.EmptyTypes, attribs);
2005-06-01 13:49:30 +04:00
if(fld.IsTransient)
{
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(typeof(NonSerializedAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
field.SetCustomAttribute(transientAttrib);
}
2006-08-17 17:18:45 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
// Instance fields can also have a ConstantValue attribute (and are inlined by the compiler),
// and ikvmstub has to export them, so we have to add a custom attribute.
if(constantValue != null)
{
2005-12-07 12:06:32 +03:00
AttributeHelper.SetConstantValue(field, constantValue);
2005-06-01 13:49:30 +04:00
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
if(isWrappedFinal)
{
methodAttribs |= MethodAttributes.SpecialName;
2006-08-15 12:50:43 +04:00
MethodBuilder getter = typeBuilder.DefineMethod(GenerateUniqueMethodName("get_" + fieldName, type, Type.EmptyTypes), methodAttribs, CallingConventions.Standard, type, Type.EmptyTypes);
2005-06-01 13:49:30 +04:00
AttributeHelper.HideFromJava(getter);
CodeEmitter ilgen = CodeEmitter.Create(getter);
2005-06-01 13:49:30 +04:00
if(fld.IsStatic)
{
ilgen.Emit(OpCodes.Ldsfld, field);
}
else
{
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldfld, field);
}
ilgen.Emit(OpCodes.Ret);
2006-10-04 13:03:18 +04:00
2006-08-15 12:50:43 +04:00
PropertyBuilder pb = typeBuilder.DefineProperty(fieldName, PropertyAttributes.None, type, Type.EmptyTypes);
2005-06-01 13:49:30 +04:00
pb.SetGetMethod(getter);
2006-08-15 12:50:43 +04:00
if(!fld.IsStatic)
{
// this method exist for use by reflection only
// (that's why it only exists for instance fields, final static fields are not settable by reflection)
MethodBuilder setter = typeBuilder.DefineMethod("__<set>", MethodAttributes.PrivateScope, CallingConventions.Standard, typeof(void), new Type[] { type });
ilgen = CodeEmitter.Create(setter);
2006-08-15 12:50:43 +04:00
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_1);
ilgen.Emit(OpCodes.Stfld, field);
ilgen.Emit(OpCodes.Ret);
pb.SetSetMethod(setter);
}
2005-06-01 13:49:30 +04:00
((GetterFieldWrapper)fw).SetGetter(getter);
2006-10-04 13:03:18 +04:00
#if STATIC_COMPILER
if(setNameSig)
{
AttributeHelper.SetNameSig(getter, fld.Name, fld.Signature);
}
if(setModifiers || fld.IsTransient)
{
AttributeHelper.SetModifiers(getter, fld.Modifiers, fld.IsInternal);
}
if(fld.DeprecatedAttribute)
{
// NOTE for better interop with other languages, we set the ObsoleteAttribute on the property itself
AttributeHelper.SetDeprecatedAttribute(pb);
}
if(fld.GenericSignature != null)
{
AttributeHelper.SetSignatureAttribute(getter, fld.GenericSignature);
}
#endif // STATIC_COMPILER
2005-01-03 11:26:21 +03:00
}
}
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER
2006-10-04 13:03:18 +04:00
if(!isWrappedFinal)
2006-05-04 12:09:56 +04:00
{
2006-10-04 13:03:18 +04:00
// if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store
// the Java modifiers
if(setModifiers)
{
AttributeHelper.SetModifiers(field, fld.Modifiers, fld.IsInternal);
}
if(setNameSig)
{
AttributeHelper.SetNameSig(field, fld.Name, fld.Signature);
}
if(fld.DeprecatedAttribute)
{
AttributeHelper.SetDeprecatedAttribute(field);
}
if(fld.GenericSignature != null)
{
AttributeHelper.SetSignatureAttribute(field, fld.GenericSignature);
}
2006-08-17 17:18:45 +04:00
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
return field;
2005-01-03 11:26:21 +03:00
}
2004-08-17 13:05:21 +04:00
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
2005-08-24 12:14:23 +04:00
{
if(clinitMethod != null)
{
ilgen.Emit(OpCodes.Call, clinitMethod);
}
}
2005-08-05 12:40:54 +04:00
internal override DynamicImpl Finish()
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if(wrapper.BaseTypeWrapper != null)
{
2005-08-05 12:40:54 +04:00
wrapper.BaseTypeWrapper.Finish();
2005-06-01 13:49:30 +04:00
}
2006-05-15 13:08:01 +04:00
#if STATIC_COMPILER
2005-06-01 13:49:30 +04:00
if(outerClassWrapper != null)
{
2005-08-05 12:40:54 +04:00
outerClassWrapper.Finish();
2005-06-01 13:49:30 +04:00
}
2006-05-15 13:08:01 +04:00
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
// NOTE there is a bug in the CLR (.NET 1.0 & 1.1 [1.2 is not yet available]) that
// causes the AppDomain.TypeResolve event to receive the incorrect type name for nested types.
// The Name in the ResolveEventArgs contains only the nested type name, not the full type name,
// for example, if the type being resolved is "MyOuterType+MyInnerType", then the event only
// receives "MyInnerType" as the name. Since we only compile inner classes as nested types
// when we're statically compiling, we can only run into this bug when we're statically compiling.
// NOTE To work around this bug, we have to make sure that all types that are going to be
// required in finished form, are finished explicitly here. It isn't clear what other types are
// required to be finished. I instrumented a static compilation of classpath.dll and this
// turned up no other cases of the TypeResolve event firing.
for(int i = 0; i < wrapper.Interfaces.Length; i++)
{
2005-08-05 12:40:54 +04:00
wrapper.Interfaces[i].Finish();
2005-06-01 13:49:30 +04:00
}
// make sure all classes are loaded, before we start finishing the type. During finishing, we
// may not run any Java code, because that might result in a request to finish the type that we
// are in the process of finishing, and this would be a problem.
2006-05-06 14:46:51 +04:00
classFile.Link(wrapper, classCache);
2005-06-01 13:49:30 +04:00
for(int i = 0; i < fields.Length; i++)
{
#if STATIC_COMPILER
if(fields[i] is AotAccessStubFieldWrapper)
{
// HACK we skip access stubs, because we want to do the methods first
// (to prevent the stub method from taking the name of a real method)
continue;
}
#endif
2005-06-01 13:49:30 +04:00
fields[i].Link();
}
for(int i = 0; i < methods.Length; i++)
{
methods[i].Link();
}
#if STATIC_COMPILER
// HACK second pass for the access stubs (see above)
for(int i = 0; i < fields.Length; i++)
{
if(fields[i] is AotAccessStubFieldWrapper)
{
fields[i].Link();
}
}
#endif
2006-05-05 15:21:15 +04:00
// this is the correct lock, FinishCore doesn't call any user code and mutates global state,
// so it needs to be protected by a lock.
lock(this)
{
return FinishCore();
}
}
private FinishedTypeImpl FinishCore()
{
2005-06-01 13:49:30 +04:00
// it is possible that the loading of the referenced classes triggered a finish of us,
// if that happens, we just return
if(finishedType != null)
{
return finishedType;
}
if(finishInProgress)
{
throw new InvalidOperationException("Recursive finish attempt for " + wrapper.Name);
}
finishInProgress = true;
2006-08-14 11:57:03 +04:00
Tracer.Info(Tracer.Compiler, "Finishing: {0}", wrapper.Name);
2005-06-01 13:49:30 +04:00
Profiler.Enter("JavaTypeImpl.Finish.Core");
try
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper declaringTypeWrapper = null;
TypeWrapper[] innerClassesTypeWrappers = TypeWrapper.EmptyArray;
// if we're an inner class, we need to attach an InnerClass attribute
ClassFile.InnerClass[] innerclasses = classFile.InnerClasses;
if (innerclasses != null)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO consider not pre-computing innerClassesTypeWrappers and declaringTypeWrapper here
ArrayList wrappers = new ArrayList();
for (int i = 0; i < innerclasses.Length; i++)
2003-10-17 12:08:31 +04:00
{
if (innerclasses[i].innerClass != 0 && innerclasses[i].outerClass != 0)
2003-10-17 12:08:31 +04:00
{
if (classFile.GetConstantPoolClassType(innerclasses[i].outerClass) == wrapper)
2005-06-01 13:49:30 +04:00
{
wrappers.Add(classFile.GetConstantPoolClassType(innerclasses[i].innerClass));
}
if (classFile.GetConstantPoolClassType(innerclasses[i].innerClass) == wrapper)
2005-06-01 13:49:30 +04:00
{
declaringTypeWrapper = classFile.GetConstantPoolClassType(innerclasses[i].outerClass);
}
2003-10-17 12:08:31 +04:00
}
}
2005-06-01 13:49:30 +04:00
innerClassesTypeWrappers = (TypeWrapper[])wrappers.ToArray(typeof(TypeWrapper));
2003-10-17 12:08:31 +04:00
}
FinishContext context = new FinishContext(classFile, wrapper, typeBuilder);
2006-09-12 13:57:36 +04:00
#if STATIC_COMPILER
context.RegisterPostFinishProc(delegate
{
if (enumBuilder != null)
{
enumBuilder.CreateType();
}
if (annotationBuilder != null)
{
annotationBuilder.Finish(this);
}
});
#endif
Type type = context.FinishImpl();
finishedType = new FinishedTypeImpl(type, innerClassesTypeWrappers, declaringTypeWrapper, wrapper.ReflectiveModifiers, Metadata.Create(classFile)
#if STATIC_COMPILER
, annotationBuilder, enumBuilder
#endif
);
return finishedType;
}
catch(Exception x)
{
JVM.CriticalFailure("Exception during finishing of: " + wrapper.Name, x);
return null;
}
finally
{
Profiler.Leave("JavaTypeImpl.Finish.Core");
}
}
#if STATIC_COMPILER
private bool IsValidAnnotationElementType(string type)
{
if(type[0] == '[')
{
type = type.Substring(1);
}
switch(type)
{
case "Z":
case "B":
case "S":
case "C":
case "I":
case "J":
case "F":
case "D":
case "Ljava.lang.String;":
case "Ljava.lang.Class;":
return true;
}
if(type.StartsWith("L") && type.EndsWith(";"))
{
try
2003-10-17 12:08:31 +04:00
{
TypeWrapper tw = wrapper.GetClassLoader().LoadClassByDottedNameFast(type.Substring(1, type.Length - 2));
if(tw != null)
2003-10-17 12:08:31 +04:00
{
if((tw.Modifiers & Modifiers.Annotation) != 0)
{
return true;
}
if((tw.Modifiers & Modifiers.Enum) != 0)
2005-06-01 13:49:30 +04:00
{
TypeWrapper enumType = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("java.lang.Enum");
if(enumType != null && tw.IsSubTypeOf(enumType))
2005-06-01 13:49:30 +04:00
{
return true;
2005-06-01 13:49:30 +04:00
}
}
2003-01-02 18:44:17 +03:00
}
2002-12-18 19:00:25 +03:00
}
catch
{
}
}
return false;
}
sealed class AnnotationBuilder : Annotation
{
private TypeBuilder annotationTypeBuilder;
private TypeBuilder attributeTypeBuilder;
private ConstructorBuilder defineConstructor;
internal AnnotationBuilder(JavaTypeImpl o)
{
// Make sure the annotation type only has valid methods
for(int i = 0; i < o.methods.Length; i++)
2002-12-18 19:00:25 +03:00
{
if(!o.methods[i].IsStatic)
2002-12-18 19:00:25 +03:00
{
if(!o.methods[i].Signature.StartsWith("()"))
2003-01-02 18:44:17 +03:00
{
return;
2006-08-14 11:57:03 +04:00
}
if(!o.IsValidAnnotationElementType(o.methods[i].Signature.Substring(2)))
2006-08-14 11:57:03 +04:00
{
return;
2002-12-18 19:00:25 +03:00
}
}
}
// we only set annotationTypeBuilder if we're valid
annotationTypeBuilder = o.typeBuilder;
TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.AnnotationAttributeBase");
// TODO attribute should be .NET serializable
TypeAttributes typeAttributes = TypeAttributes.Class | TypeAttributes.Sealed;
if(o.outerClassWrapper != null)
{
if(o.wrapper.IsPublic)
{
typeAttributes |= TypeAttributes.NestedPublic;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
else
2004-08-17 13:05:21 +04:00
{
typeAttributes |= TypeAttributes.NestedAssembly;
}
attributeTypeBuilder = o.outerClassWrapper.TypeAsBuilder.DefineNestedType(GetInnerClassName(o.outerClassWrapper.Name, o.classFile.Name) + "Attribute", typeAttributes, annotationAttributeBaseType.TypeAsBaseType);
}
else
{
if(o.wrapper.IsPublic)
{
typeAttributes |= TypeAttributes.Public;
}
else
{
typeAttributes |= TypeAttributes.NotPublic;
}
attributeTypeBuilder = o.wrapper.classLoader.GetTypeWrapperFactory().ModuleBuilder.DefineType(o.classFile.Name + "Attribute", typeAttributes, annotationAttributeBaseType.TypeAsBaseType);
}
if(o.wrapper.IsPublic)
{
// In the Java world, the class appears as a non-public proxy class
AttributeHelper.SetModifiers(attributeTypeBuilder, Modifiers.Final, false);
}
// NOTE we "abuse" the InnerClassAttribute to add a custom attribute to name the class "$Proxy[Annotation]" in the Java world
int dotindex = o.classFile.Name.LastIndexOf('.') + 1;
AttributeHelper.SetInnerClass(attributeTypeBuilder, o.classFile.Name.Substring(0, dotindex) + "$Proxy" + o.classFile.Name.Substring(dotindex), Modifiers.Final);
attributeTypeBuilder.AddInterfaceImplementation(o.typeBuilder);
AttributeHelper.SetImplementsAttribute(attributeTypeBuilder, new TypeWrapper[] { o.wrapper });
if(o.classFile.Annotations != null)
{
foreach(object[] def in o.classFile.Annotations)
{
if(def[1].Equals("Ljava/lang/annotation/Target;"))
{
for(int i = 2; i < def.Length; i += 2)
{
if(def[i].Equals("value"))
2004-08-17 13:05:21 +04:00
{
object[] val = def[i + 1] as object[];
if(val != null
&& val.Length > 0
&& val[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY))
2004-08-17 13:05:21 +04:00
{
AttributeTargets targets = 0;
for(int j = 1; j < val.Length; j++)
2005-06-01 13:49:30 +04:00
{
object[] eval = val[j] as object[];
if(eval != null
&& eval.Length == 3
&& eval[0].Equals(AnnotationDefaultAttribute.TAG_ENUM)
&& eval[1].Equals("Ljava/lang/annotation/ElementType;"))
{
switch((string)eval[2])
{
case "ANNOTATION_TYPE":
targets |= AttributeTargets.Interface;
break;
case "CONSTRUCTOR":
targets |= AttributeTargets.Constructor;
break;
case "FIELD":
targets |= AttributeTargets.Field;
break;
case "LOCAL_VARIABLE":
break;
case "METHOD":
targets |= AttributeTargets.Method;
break;
case "PACKAGE":
targets |= AttributeTargets.Interface;
break;
case "PARAMETER":
targets |= AttributeTargets.Parameter;
break;
case "TYPE":
targets |= AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum;
break;
}
}
2005-06-01 13:49:30 +04:00
}
CustomAttributeBuilder cab2 = new CustomAttributeBuilder(typeof(AttributeUsageAttribute).GetConstructor(new Type[] { typeof(AttributeTargets) }), new object[] { targets });
attributeTypeBuilder.SetCustomAttribute(cab2);
2004-08-17 13:05:21 +04:00
}
}
2003-01-02 18:44:17 +03:00
}
2005-03-01 11:24:54 +03:00
}
2002-12-27 12:01:16 +03:00
}
2003-01-02 18:44:17 +03:00
}
defineConstructor = attributeTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(object[]) });
AttributeHelper.SetEditorBrowsableNever(defineConstructor);
}
private static Type TypeWrapperToAnnotationParameterType(TypeWrapper tw)
{
bool isArray = false;
if(tw.IsArray)
{
isArray = true;
tw = tw.ElementTypeWrapper;
}
if(tw.Annotation != null)
{
// we don't support Annotation args
return null;
}
else
{
Type argType;
if(tw == CoreClasses.java.lang.Class.Wrapper)
{
argType = typeof(Type);
}
else if(tw.EnumType != null)
{
argType = tw.EnumType;
}
else
{
argType = tw.TypeAsSignatureType;
}
if(isArray)
{
argType = ArrayTypeWrapper.MakeArrayType(argType, 1);
}
return argType;
}
}
internal string AttributeTypeName
{
get
{
if(attributeTypeBuilder != null)
{
return attributeTypeBuilder.FullName;
}
return null;
}
}
private static void EmitSetValueCall(TypeWrapper annotationAttributeBaseType, CodeEmitter ilgen, string name, TypeWrapper tw, int argIndex)
{
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldstr, name);
ilgen.Emit(OpCodes.Ldarg_S, (byte)argIndex);
if(tw.TypeAsSignatureType.IsValueType)
{
ilgen.Emit(OpCodes.Box, tw.TypeAsSignatureType);
}
else if(tw.EnumType != null)
{
ilgen.Emit(OpCodes.Box, tw.EnumType);
}
MethodWrapper setValueMethod = annotationAttributeBaseType.GetMethodWrapper("setValue", "(Ljava.lang.String;Ljava.lang.Object;)V", false);
setValueMethod.Link();
setValueMethod.EmitCall(ilgen);
}
internal void Finish(JavaTypeImpl o)
{
if(annotationTypeBuilder == null)
2003-05-30 16:08:59 +04:00
{
// not a valid annotation type
return;
}
TypeWrapper annotationAttributeBaseType = ClassLoaderWrapper.LoadClassCritical("ikvm.internal.AnnotationAttributeBase");
annotationAttributeBaseType.Finish();
2003-05-30 16:08:59 +04:00
int requiredArgCount = 0;
int valueArg = -1;
bool unsupported = false;
for(int i = 0; i < o.methods.Length; i++)
{
if(!o.methods[i].IsStatic)
2003-05-13 00:00:15 +04:00
{
if(valueArg == -1 && o.methods[i].Name == "value")
2005-06-01 13:49:30 +04:00
{
valueArg = i;
2005-06-01 13:49:30 +04:00
}
if(o.classFile.Methods[i].AnnotationDefault == null)
2004-08-17 13:05:21 +04:00
{
if(TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType) == null)
2004-08-17 13:05:21 +04:00
{
unsupported = true;
break;
2004-08-17 13:05:21 +04:00
}
requiredArgCount++;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
}
}
ConstructorBuilder defaultConstructor = attributeTypeBuilder.DefineConstructor(unsupported || requiredArgCount > 0 ? MethodAttributes.Private : MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
CodeEmitter ilgen;
if(!unsupported)
{
if(requiredArgCount > 0)
{
Type[] args = new Type[requiredArgCount];
for(int i = 0, j = 0; i < o.methods.Length; i++)
2005-06-01 13:49:30 +04:00
{
if(!o.methods[i].IsStatic)
{
if(o.classFile.Methods[i].AnnotationDefault == null)
{
args[j++] = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType);
}
}
2005-06-01 13:49:30 +04:00
}
ConstructorBuilder reqArgConstructor = attributeTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, args);
AttributeHelper.HideFromJava(reqArgConstructor);
ilgen = CodeEmitter.Create(reqArgConstructor);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, defaultConstructor);
for(int i = 0, j = 0; i < o.methods.Length; i++)
2004-08-17 13:05:21 +04:00
{
if(!o.methods[i].IsStatic)
2004-08-17 13:05:21 +04:00
{
if(o.classFile.Methods[i].AnnotationDefault == null)
{
reqArgConstructor.DefineParameter(++j, ParameterAttributes.None, o.methods[i].Name);
EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, j);
}
2004-08-17 13:05:21 +04:00
}
}
ilgen.Emit(OpCodes.Ret);
2004-08-17 13:05:21 +04:00
}
else if(valueArg != -1)
2005-06-01 13:49:30 +04:00
{
// We don't have any required parameters, but we do have an optional "value" parameter,
// so we create an additional constructor (the default constructor will be public in this case)
// that accepts the value parameter.
Type argType = TypeWrapperToAnnotationParameterType(o.methods[valueArg].ReturnType);
if(argType != null)
{
ConstructorBuilder cb = attributeTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { argType });
AttributeHelper.HideFromJava(cb);
cb.DefineParameter(1, ParameterAttributes.None, "value");
ilgen = CodeEmitter.Create(cb);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, defaultConstructor);
EmitSetValueCall(annotationAttributeBaseType, ilgen, "value", o.methods[valueArg].ReturnType, 1);
ilgen.Emit(OpCodes.Ret);
}
}
}
ilgen = CodeEmitter.Create(defaultConstructor);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldtoken, annotationTypeBuilder);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.GetClassFromTypeHandle);
CoreClasses.java.lang.Class.Wrapper.EmitCheckcast(null, ilgen);
annotationAttributeBaseType.GetMethodWrapper("<init>", "(Ljava.lang.Class;)V", false).EmitCall(ilgen);
ilgen.Emit(OpCodes.Ret);
ilgen = CodeEmitter.Create(defineConstructor);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, defaultConstructor);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldarg_1);
annotationAttributeBaseType.GetMethodWrapper("setDefinition", "([Ljava.lang.Object;)V", false).EmitCall(ilgen);
ilgen.Emit(OpCodes.Ret);
MethodWrapper getValueMethod = annotationAttributeBaseType.GetMethodWrapper("getValue", "(Ljava.lang.String;)Ljava.lang.Object;", false);
MethodWrapper getByteValueMethod = annotationAttributeBaseType.GetMethodWrapper("getByteValue", "(Ljava.lang.String;)B", false);
MethodWrapper getBooleanValueMethod = annotationAttributeBaseType.GetMethodWrapper("getBooleanValue", "(Ljava.lang.String;)Z", false);
MethodWrapper getCharValueMethod = annotationAttributeBaseType.GetMethodWrapper("getCharValue", "(Ljava.lang.String;)C", false);
MethodWrapper getShortValueMethod = annotationAttributeBaseType.GetMethodWrapper("getShortValue", "(Ljava.lang.String;)S", false);
MethodWrapper getIntValueMethod = annotationAttributeBaseType.GetMethodWrapper("getIntValue", "(Ljava.lang.String;)I", false);
MethodWrapper getFloatValueMethod = annotationAttributeBaseType.GetMethodWrapper("getFloatValue", "(Ljava.lang.String;)F", false);
MethodWrapper getLongValueMethod = annotationAttributeBaseType.GetMethodWrapper("getLongValue", "(Ljava.lang.String;)J", false);
MethodWrapper getDoubleValueMethod = annotationAttributeBaseType.GetMethodWrapper("getDoubleValue", "(Ljava.lang.String;)D", false);
for(int i = 0; i < o.methods.Length; i++)
{
// skip <clinit>
if(!o.methods[i].IsStatic)
2005-11-01 17:01:42 +03:00
{
MethodBuilder mb = attributeTypeBuilder.DefineMethod(o.methods[i].Name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot, o.methods[i].ReturnTypeForDefineMethod, o.methods[i].GetParametersForDefineMethod());
attributeTypeBuilder.DefineMethodOverride(mb, (MethodInfo)o.methods[i].GetMethod());
ilgen = CodeEmitter.Create(mb);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldstr, o.methods[i].Name);
if(o.methods[i].ReturnType.IsPrimitive)
2005-11-01 17:01:42 +03:00
{
if(o.methods[i].ReturnType == PrimitiveTypeWrapper.BYTE)
2005-11-01 17:01:42 +03:00
{
getByteValueMethod.EmitCall(ilgen);
}
else if(o.methods[i].ReturnType == PrimitiveTypeWrapper.BOOLEAN)
{
getBooleanValueMethod.EmitCall(ilgen);
}
else if(o.methods[i].ReturnType == PrimitiveTypeWrapper.CHAR)
{
getCharValueMethod.EmitCall(ilgen);
}
else if(o.methods[i].ReturnType == PrimitiveTypeWrapper.SHORT)
{
getShortValueMethod.EmitCall(ilgen);
}
else if(o.methods[i].ReturnType == PrimitiveTypeWrapper.INT)
{
getIntValueMethod.EmitCall(ilgen);
}
else if(o.methods[i].ReturnType == PrimitiveTypeWrapper.FLOAT)
{
getFloatValueMethod.EmitCall(ilgen);
}
else if(o.methods[i].ReturnType == PrimitiveTypeWrapper.LONG)
{
getLongValueMethod.EmitCall(ilgen);
}
else if(o.methods[i].ReturnType == PrimitiveTypeWrapper.DOUBLE)
{
getDoubleValueMethod.EmitCall(ilgen);
}
else
{
throw new InvalidOperationException();
}
}
else
{
getValueMethod.EmitCall(ilgen);
o.methods[i].ReturnType.EmitCheckcast(null, ilgen);
}
ilgen.Emit(OpCodes.Ret);
if(o.classFile.Methods[i].AnnotationDefault != null
&& !(o.methods[i].Name == "value" && requiredArgCount == 0))
{
// now add a .NET property for this annotation optional parameter
Type argType = TypeWrapperToAnnotationParameterType(o.methods[i].ReturnType);
if(argType != null)
{
PropertyBuilder pb = attributeTypeBuilder.DefineProperty(o.methods[i].Name, PropertyAttributes.None, argType, Type.EmptyTypes);
AttributeHelper.HideFromJava(pb);
MethodBuilder setter = attributeTypeBuilder.DefineMethod("set_" + o.methods[i].Name, MethodAttributes.Public, typeof(void), new Type[] { argType });
AttributeHelper.HideFromJava(setter);
pb.SetSetMethod(setter);
ilgen = CodeEmitter.Create(setter);
EmitSetValueCall(annotationAttributeBaseType, ilgen, o.methods[i].Name, o.methods[i].ReturnType, 1);
ilgen.Emit(OpCodes.Ret);
MethodBuilder getter = attributeTypeBuilder.DefineMethod("get_" + o.methods[i].Name, MethodAttributes.Public, argType, Type.EmptyTypes);
AttributeHelper.HideFromJava(getter);
pb.SetGetMethod(getter);
// TODO implement the getter method
CodeEmitter.Create(getter).ThrowException(typeof(NotImplementedException));
2005-11-01 17:01:42 +03:00
}
2006-04-20 11:30:59 +04:00
}
}
2006-06-15 16:29:11 +04:00
}
attributeTypeBuilder.CreateType();
}
2006-04-20 11:30:59 +04:00
internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation)
{
if(annotationTypeBuilder != null)
2006-06-15 16:29:11 +04:00
{
annotation = QualifyClassNames(loader, annotation);
tb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor, new object[] { annotation }));
2006-06-15 16:29:11 +04:00
}
}
2006-04-20 11:30:59 +04:00
internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation)
{
if(annotationTypeBuilder != null)
2006-06-15 16:29:11 +04:00
{
annotation = QualifyClassNames(loader, annotation);
mb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor, new object[] { annotation }));
2005-10-01 15:16:11 +04:00
}
}
2005-10-01 15:16:11 +04:00
internal override void Apply(ClassLoaderWrapper loader, ConstructorBuilder cb, object annotation)
{
if(annotationTypeBuilder != null)
2005-01-03 11:26:21 +03:00
{
annotation = QualifyClassNames(loader, annotation);
cb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor, new object[] { annotation }));
2005-01-03 11:26:21 +03:00
}
}
internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation)
{
if(annotationTypeBuilder != null)
2005-01-03 11:26:21 +03:00
{
annotation = QualifyClassNames(loader, annotation);
fb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor, new object[] { annotation }));
2005-01-03 11:26:21 +03:00
}
2005-11-01 17:01:42 +03:00
}
internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation)
2005-11-01 17:01:42 +03:00
{
if(annotationTypeBuilder != null)
{
annotation = QualifyClassNames(loader, annotation);
pb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor, new object[] { annotation }));
}
2005-11-01 17:01:42 +03:00
}
internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation)
2005-11-01 17:01:42 +03:00
{
if(annotationTypeBuilder != null)
{
annotation = QualifyClassNames(loader, annotation);
ab.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor, new object[] { annotation }));
}
}
internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation)
{
if(annotationTypeBuilder != null)
{
annotation = QualifyClassNames(loader, annotation);
pb.SetCustomAttribute(new CustomAttributeBuilder(defineConstructor, new object[] { annotation }));
}
2005-11-01 17:01:42 +03:00
}
}
#endif // STATIC_COMPILER
2005-11-01 17:01:42 +03:00
internal override TypeWrapper[] InnerClasses
{
get
{
throw new InvalidOperationException("InnerClasses is only available for finished types");
}
}
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
throw new InvalidOperationException("DeclaringTypeWrapper is only available for finished types");
}
}
internal override Modifiers ReflectiveModifiers
{
get
{
ClassFile.InnerClass[] innerclasses = classFile.InnerClasses;
if(innerclasses != null)
{
for(int i = 0; i < innerclasses.Length; i++)
{
if(innerclasses[i].innerClass != 0)
{
if(classFile.GetConstantPoolClass(innerclasses[i].innerClass) == wrapper.Name)
{
return innerclasses[i].accessFlags;
}
}
}
}
return classFile.Modifiers;
}
}
private void UpdateClashTable()
{
lock(this)
{
if(memberclashtable == null)
{
memberclashtable = new Hashtable();
for(int i = 0; i < methods.Length; i++)
{
// TODO at the moment we don't support constructor signature clash resolving, so we better
// not put them in the clash table
if(methods[i].IsLinked && methods[i].GetMethod() != null && methods[i].Name != "<init>")
{
string key = GenerateClashKey("method", methods[i].RealName, methods[i].ReturnTypeForDefineMethod, methods[i].GetParametersForDefineMethod());
memberclashtable.Add(key, key);
}
}
}
}
}
private static string GenerateClashKey(string type, string name, Type retOrFieldType, Type[] args)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder(type);
sb.Append(':').Append(name).Append(':').Append(retOrFieldType.FullName);
if(args != null)
{
foreach(Type t in args)
{
sb.Append(':').Append(t.FullName);
}
}
return sb.ToString();
}
internal static ConstructorBuilder DefineClassInitializer(TypeBuilder typeBuilder)
{
if (typeBuilder.IsInterface)
{
// LAMESPEC the ECMA spec says (part. I, sect. 8.5.3.2) that all interface members must be public, so we make
// the class constructor public.
// NOTE it turns out that on .NET 2.0 this isn't necessary anymore (neither Ref.Emit nor the CLR verifier complain about it),
// but the C# compiler still considers interfaces with non-public methods to be invalid, so to keep interop with C# we have
// to keep making the .cctor method public.
return typeBuilder.DefineConstructor(MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
}
// NOTE we don't need to record the modifiers here, because they aren't visible from Java reflection
return typeBuilder.DefineTypeInitializer();
}
// this finds the method that md is going to be overriding
private MethodWrapper FindBaseMethod(string name, string sig, out bool explicitOverride)
{
Debug.Assert(!classFile.IsInterface);
Debug.Assert(name != "<init>");
explicitOverride = false;
TypeWrapper tw = wrapper.BaseTypeWrapper;
while(tw != null)
{
MethodWrapper baseMethod = tw.GetMethodWrapper(name, sig, true);
if(baseMethod == null)
{
return null;
}
// here are the complex rules for determining whether this method overrides the method we found
// RULE 1: final methods may not be overridden
// (note that we intentionally not check IsStatic here!)
if(baseMethod.IsFinal
&& !baseMethod.IsPrivate
&& (baseMethod.IsPublic || baseMethod.IsProtected || baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)))
{
throw new VerifyError("final method " + baseMethod.Name + baseMethod.Signature + " in " + baseMethod.DeclaringType.Name + " is overriden in " + wrapper.Name);
}
// RULE 1a: static methods are ignored (other than the RULE 1 check)
if(baseMethod.IsStatic)
{
}
// RULE 2: public & protected methods can be overridden (package methods are handled by RULE 4)
// (by public, protected & *package* methods [even if they are in a different package])
else if(baseMethod.IsPublic || baseMethod.IsProtected)
{
// if we already encountered a package method, we cannot override the base method of
// that package method
if(explicitOverride)
{
explicitOverride = false;
return null;
}
return baseMethod;
}
// RULE 3: private and static methods are ignored
else if(!baseMethod.IsPrivate)
{
// RULE 4: package methods can only be overridden in the same package
if(baseMethod.DeclaringType.IsPackageAccessibleFrom(wrapper)
|| (baseMethod.IsInternal && baseMethod.DeclaringType.GetClassLoader().InternalsVisibleTo(wrapper.GetClassLoader())))
{
return baseMethod;
}
// since we encountered a method with the same name/signature that we aren't overriding,
// we need to specify an explicit override
// NOTE we only do this if baseMethod isn't private, because if it is, Reflection.Emit
// will complain about the explicit MethodOverride (possibly a bug)
explicitOverride = true;
}
tw = baseMethod.DeclaringType.BaseTypeWrapper;
}
return null;
}
internal string GenerateUniqueMethodName(string basename, MethodWrapper mw)
{
return GenerateUniqueMethodName(basename, mw.ReturnTypeForDefineMethod, mw.GetParametersForDefineMethod());
}
internal string GenerateUniqueMethodName(string basename, Type returnType, Type[] parameterTypes)
2006-04-10 13:09:09 +04:00
{
string name = basename;
string key = GenerateClashKey("method", name, returnType, parameterTypes);
UpdateClashTable();
lock (memberclashtable.SyncRoot)
2006-04-10 13:09:09 +04:00
{
for (int clashcount = 0; memberclashtable.ContainsKey(key); clashcount++)
2006-04-10 13:09:09 +04:00
{
name = basename + "_" + clashcount;
key = GenerateClashKey("method", name, returnType, parameterTypes);
2006-04-10 13:09:09 +04:00
}
memberclashtable.Add(key, key);
2006-04-10 13:09:09 +04:00
}
return name;
2006-04-10 13:09:09 +04:00
}
private static MethodInfo GetBaseFinalizeMethod(TypeWrapper wrapper, out bool clash)
2005-11-01 17:01:42 +03:00
{
clash = false;
for(;;)
2005-11-01 17:01:42 +03:00
{
// HACK we get called during method linking (which is probably a bad idea) and
// it is possible for the base type not to be finished yet, so we look at the
// private state of the unfinished base types to find the finalize method.
DynamicTypeWrapper dtw = wrapper as DynamicTypeWrapper;
if(dtw == null)
{
break;
}
JavaTypeImpl impl = dtw.impl as JavaTypeImpl;
if(impl == null)
{
break;
}
MethodWrapper mw = dtw.GetMethodWrapper(StringConstants.FINALIZE, StringConstants.SIG_VOID, false);
if(mw != null)
{
mw.Link();
}
if(impl.finalizeMethod != null)
{
return impl.finalizeMethod;
}
wrapper = wrapper.BaseTypeWrapper;
2005-11-01 17:01:42 +03:00
}
Type type = wrapper.TypeAsBaseType;
MethodInfo baseFinalize = type.GetMethod("__<Finalize>", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
if(baseFinalize != null)
2005-11-01 17:01:42 +03:00
{
return baseFinalize;
2005-11-01 17:01:42 +03:00
}
while(type != null)
2005-11-01 17:01:42 +03:00
{
foreach(MethodInfo m in type.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
2005-10-01 15:16:11 +04:00
{
if(m.Name == "Finalize"
&& m.ReturnType == typeof(void)
&& m.GetParameters().Length == 0)
2005-10-01 15:16:11 +04:00
{
if(m.GetBaseDefinition().DeclaringType == typeof(object))
2005-11-01 17:01:42 +03:00
{
return m;
2005-10-01 15:16:11 +04:00
}
clash = true;
2005-10-01 15:16:11 +04:00
}
}
type = type.BaseType;
2005-11-01 17:01:42 +03:00
}
return null;
2005-11-01 17:01:42 +03:00
}
private MethodAttributes GetPropertyAccess(MethodWrapper mw)
2005-11-01 17:01:42 +03:00
{
string sig = mw.ReturnType.SigName;
if(sig == "V")
2005-11-01 17:01:42 +03:00
{
sig = mw.GetParameters()[0].SigName;
}
int access = -1;
foreach(ClassFile.Field field in classFile.Fields)
{
if(field.IsProperty
&& field.IsStatic == mw.IsStatic
&& field.Signature == sig
&& (field.PropertyGetter == mw.Name || field.PropertySetter == mw.Name))
2005-11-01 17:01:42 +03:00
{
int nacc;
if(field.IsPublic)
2005-10-01 15:16:11 +04:00
{
nacc = 3;
2005-10-01 15:16:11 +04:00
}
else if(field.IsProtected)
2005-10-01 15:16:11 +04:00
{
nacc = 2;
}
else if(field.IsPrivate)
{
nacc = 0;
2005-10-01 15:16:11 +04:00
}
2005-11-01 17:01:42 +03:00
else
{
nacc = 1;
}
if(nacc > access)
{
access = nacc;
2005-11-01 17:01:42 +03:00
}
2005-10-01 15:16:11 +04:00
}
}
switch(access)
{
case 0:
return MethodAttributes.Private;
case 1:
return MethodAttributes.Assembly;
case 2:
return MethodAttributes.FamORAssem;
case 3:
return MethodAttributes.Public;
default:
throw new InvalidOperationException();
}
}
private MethodBase GenerateMethod(int index, bool unloadableOverrideStub)
{
methods[index].AssertLinked();
Profiler.Enter("JavaTypeImpl.GenerateMethod");
try
{
if(index >= classFile.Methods.Length)
2005-10-01 15:16:11 +04:00
{
if(methods[index].IsMirandaMethod)
2005-11-01 17:01:42 +03:00
{
// We're a Miranda method
Debug.Assert(baseMethods[index].DeclaringType.IsInterface);
string name = GenerateUniqueMethodName(methods[index].Name, baseMethods[index]);
MethodBuilder mb = typeBuilder.DefineMethod(methods[index].Name, MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Abstract | MethodAttributes.CheckAccessOnOverride, methods[index].ReturnTypeForDefineMethod, methods[index].GetParametersForDefineMethod());
AttributeHelper.HideFromReflection(mb);
#if STATIC_COMPILER
if(unloadableOverrideStub || name != methods[index].Name)
{
// instead of creating an override stub, we created the Miranda method with the proper signature and
// decorate it with a NameSigAttribute that contains the real signature
AttributeHelper.SetNameSig(mb, methods[index].Name, methods[index].Signature);
}
#endif // STATIC_COMPILER
// if we changed the name or if the interface method name is remapped, we need to add an explicit methodoverride.
if(!baseMethods[index].IsDynamicOnly && name != baseMethods[index].RealName)
{
typeBuilder.DefineMethodOverride(mb, (MethodInfo)baseMethods[index].GetMethod());
}
return mb;
}
else if(methods[index].IsAccessStub)
{
Debug.Assert(!baseMethods[index].HasCallerID);
MethodAttributes stubattribs = baseMethods[index].IsPublic ? MethodAttributes.Public : MethodAttributes.FamORAssem;
stubattribs |= MethodAttributes.HideBySig;
if(baseMethods[index].IsStatic)
{
stubattribs |= MethodAttributes.Static;
}
else
{
stubattribs |= MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual;
if(baseMethods[index].IsAbstract && wrapper.IsAbstract)
{
stubattribs |= MethodAttributes.Abstract;
}
if(baseMethods[index].IsFinal)
{
// NOTE final methods still need to be virtual, because a subclass may need this method to
// implement an interface method
stubattribs |= MethodAttributes.Final | MethodAttributes.NewSlot;
}
}
MethodBuilder mb = typeBuilder.DefineMethod(methods[index].Name, stubattribs, methods[index].ReturnTypeForDefineMethod, methods[index].GetParametersForDefineMethod());
AttributeHelper.HideFromReflection(mb);
if(!baseMethods[index].IsAbstract)
{
CodeEmitter ilgen = CodeEmitter.Create(mb);
int argc = methods[index].GetParametersForDefineMethod().Length + (methods[index].IsStatic ? 0 : 1);
for(int i = 0; i < argc; i++)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)i);
}
baseMethods[index].EmitCall(ilgen);
ilgen.Emit(OpCodes.Ret);
}
else if(!wrapper.IsAbstract)
{
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.AbstractMethodError", wrapper.Name + "." + methods[index].Name + methods[index].Signature);
}
return mb;
2005-11-01 17:01:42 +03:00
}
else
2005-10-01 15:16:11 +04:00
{
throw new InvalidOperationException();
2005-10-01 15:16:11 +04:00
}
}
ClassFile.Method m = classFile.Methods[index];
MethodBase method;
bool setNameSig = methods[index].ReturnType.IsErasedOrBoxedPrimitiveOrRemapped;
foreach(TypeWrapper tw in methods[index].GetParameters())
2005-11-01 17:01:42 +03:00
{
setNameSig |= tw.IsErasedOrBoxedPrimitiveOrRemapped;
2005-11-01 17:01:42 +03:00
}
bool setModifiers = false;
if(methods[index].HasCallerID && (m.Modifiers & Modifiers.VarArgs) != 0)
2006-04-23 14:46:51 +04:00
{
// the implicit callerID parameter was added at the end so that means we shouldn't use ParamArrayAttribute,
// so we need to explicitly record that the method is varargs
setModifiers = true;
2006-04-23 14:46:51 +04:00
}
MethodAttributes attribs = MethodAttributes.HideBySig;
if(m.IsNative)
2006-12-28 10:46:21 +03:00
{
if(wrapper.IsPInvokeMethod(m))
{
// this doesn't appear to be necessary, but we use the flag in Finish to know
// that we shouldn't emit a method body
attribs |= MethodAttributes.PinvokeImpl;
}
else
{
setModifiers = true;
}
2006-12-28 10:46:21 +03:00
}
if(methods[index].IsPropertyAccessor)
2006-12-28 10:46:21 +03:00
{
attribs |= GetPropertyAccess(methods[index]);
attribs |= MethodAttributes.SpecialName;
setModifiers = true;
2006-12-28 10:46:21 +03:00
}
else
{
if(m.IsPrivate)
2006-12-28 10:46:21 +03:00
{
attribs |= MethodAttributes.Private;
2006-12-28 10:46:21 +03:00
}
else if(m.IsProtected)
2006-12-28 10:46:21 +03:00
{
attribs |= MethodAttributes.FamORAssem;
2006-12-28 10:46:21 +03:00
}
else if(m.IsPublic)
2006-12-28 10:46:21 +03:00
{
attribs |= MethodAttributes.Public;
2006-12-28 10:46:21 +03:00
}
else
2006-12-28 10:46:21 +03:00
{
attribs |= MethodAttributes.Assembly;
2006-12-28 10:46:21 +03:00
}
}
if(ReferenceEquals(m.Name, StringConstants.INIT))
2006-05-15 13:08:01 +04:00
{
Type[][] modopt = null;
if(setNameSig)
2006-05-15 13:08:01 +04:00
{
// we add optional modifiers to make the signature unique
TypeWrapper[] parameters = methods[index].GetParameters();
modopt = new Type[parameters.Length][];
for(int i = 0; i < parameters.Length; i++)
{
if(parameters[i].IsGhostArray)
{
TypeWrapper elemTypeWrapper = parameters[i];
while(elemTypeWrapper.IsArray)
{
elemTypeWrapper = elemTypeWrapper.ElementTypeWrapper;
}
modopt[i] = new Type[] { elemTypeWrapper.TypeAsTBD };
}
else if(parameters[i].IsBoxedPrimitive)
{
modopt[i] = new Type[] { typeof(object) };
}
else if(parameters[i].IsRemapped && parameters[i] is DotNetTypeWrapper)
{
modopt[i] = new Type[] { parameters[i].TypeAsSignatureType };
}
else if(parameters[i].IsUnloadable)
{
modopt[i] = new Type[] { wrapper.classLoader.GetTypeWrapperFactory().DefineUnloadable(parameters[i].Name) };
}
}
2006-05-15 13:08:01 +04:00
}
// strictfp is the only modifier that a constructor can have
if(m.IsStrictfp)
{
setModifiers = true;
}
method = typeBuilder.DefineConstructor(attribs, CallingConventions.Standard, methods[index].GetParametersForDefineMethod(), null, modopt);
((ConstructorBuilder)method).SetImplementationFlags(MethodImplAttributes.NoInlining);
2006-12-28 10:46:21 +03:00
}
else if(m.IsClassInitializer)
2006-04-05 15:04:43 +04:00
{
method = DefineClassInitializer(typeBuilder);
2006-04-05 15:04:43 +04:00
}
else
2006-12-28 10:46:21 +03:00
{
if(m.IsAbstract)
2006-12-28 10:46:21 +03:00
{
// only if the classfile is abstract, we make the CLR method abstract, otherwise,
// we have to generate a method that throws an AbstractMethodError (because the JVM
// allows abstract methods in non-abstract classes)
if(classFile.IsAbstract)
2006-12-28 10:46:21 +03:00
{
if(classFile.IsPublic && !classFile.IsFinal && !(m.IsPublic || m.IsProtected))
2006-12-28 10:46:21 +03:00
{
setModifiers = true;
2006-12-28 10:46:21 +03:00
}
else
{
attribs |= MethodAttributes.Abstract;
}
}
else
{
setModifiers = true;
2006-12-28 10:46:21 +03:00
}
}
if(m.IsFinal)
2006-12-28 10:46:21 +03:00
{
if(!m.IsStatic && !m.IsPrivate)
2006-12-28 10:46:21 +03:00
{
attribs |= MethodAttributes.Final;
2006-12-28 10:46:21 +03:00
}
else
2006-12-28 10:46:21 +03:00
{
setModifiers = true;
2006-12-28 10:46:21 +03:00
}
}
if(m.IsStatic)
2006-12-28 10:46:21 +03:00
{
attribs |= MethodAttributes.Static;
if(m.IsSynchronized)
2006-12-28 10:46:21 +03:00
{
setModifiers = true;
2006-12-28 10:46:21 +03:00
}
}
else if(!m.IsPrivate)
2005-11-01 17:01:42 +03:00
{
attribs |= MethodAttributes.Virtual | MethodAttributes.CheckAccessOnOverride;
}
string name = m.Name;
#if STATIC_COMPILER
if((m.Modifiers & Modifiers.Bridge) != 0 && (m.IsPublic || m.IsProtected) && wrapper.IsPublic)
{
string sigbase = m.Signature.Substring(0, m.Signature.LastIndexOf(')') + 1);
foreach(MethodWrapper mw in methods)
2005-11-01 17:01:42 +03:00
{
if(mw.Name == m.Name && mw.Signature.StartsWith(sigbase) && mw.Signature != m.Signature)
2005-11-01 17:01:42 +03:00
{
// To prevent bridge methods with covariant return types from confusing
// other .NET compilers (like C#), we rename the bridge method.
name = "<bridge>" + name;
setNameSig = true;
break;
2005-11-01 17:01:42 +03:00
}
}
}
#endif
// if a method is virtual, we need to find the method it overrides (if any), for several reasons:
// - if we're overriding a method that has a different name (e.g. some of the virtual methods
// in System.Object [Equals <-> equals]) we need to add an explicit MethodOverride
// - if one of the base classes has a similar method that is private (or package) that we aren't
// overriding, we need to specify an explicit MethodOverride
MethodWrapper baseMce = baseMethods[index];
bool explicitOverride = methods[index].IsExplicitOverride;
if((attribs & MethodAttributes.Virtual) != 0 && !classFile.IsInterface)
{
// make sure the base method is already defined
Debug.Assert(baseMce == null || baseMce.GetMethod() != null);
if(baseMce == null || baseMce.DeclaringType.IsInterface)
{
// we need to set NewSlot here, to prevent accidentally overriding methods
// (for example, if a Java class has a method "boolean Equals(object)", we don't want that method
// to override System.Object.Equals)
attribs |= MethodAttributes.NewSlot;
}
else
{
// if we have a method overriding a more accessible method (the JVM allows this), we need to make the
// method more accessible, because otherwise the CLR will complain that we're reducing access
MethodBase baseMethod = baseMce.GetMethod();
if((baseMethod.IsPublic && !m.IsPublic) ||
((baseMethod.IsFamily || baseMethod.IsFamilyOrAssembly) && !m.IsPublic && !m.IsProtected) ||
(!m.IsPublic && !m.IsProtected && !baseMce.DeclaringType.IsPackageAccessibleFrom(wrapper)))
2005-11-01 17:01:42 +03:00
{
attribs &= ~MethodAttributes.MemberAccessMask;
attribs |= baseMethod.IsPublic ? MethodAttributes.Public : MethodAttributes.FamORAssem;
setModifiers = true;
2005-11-01 17:01:42 +03:00
}
}
}
MethodBuilder mb = null;
#if STATIC_COMPILER
mb = wrapper.DefineGhostMethod(name, attribs, methods[index]);
#endif
if(mb == null)
{
bool needFinalize = false;
bool needDispatch = false;
bool finalizeClash = false;
MethodInfo baseFinalize = null;
if(baseMce != null && ReferenceEquals(m.Name, StringConstants.FINALIZE) && ReferenceEquals(m.Signature, StringConstants.SIG_VOID))
{
baseFinalize = GetBaseFinalizeMethod(wrapper.BaseTypeWrapper, out finalizeClash);
if(baseMce.RealName == "Finalize")
2005-11-01 17:01:42 +03:00
{
// We're overriding Finalize (that was renamed to finalize by DotNetTypeWrapper)
// in a non-Java base class.
attribs |= MethodAttributes.NewSlot;
needFinalize = true;
needDispatch = true;
2005-11-01 17:01:42 +03:00
}
else if(baseMce.DeclaringType == CoreClasses.java.lang.Object.Wrapper)
2005-11-01 17:01:42 +03:00
{
// This type is the first type in the hierarchy to introduce a finalize method
// (other than the one in java.lang.Object obviously), so we need to override
// the real Finalize method and emit a dispatch call to our finalize method.
needFinalize = true;
needDispatch = true;
2005-11-01 17:01:42 +03:00
}
else if(m.IsFinal)
2005-11-01 17:01:42 +03:00
{
// One of our base classes already has a finalize method, so we already are
// hooked into the real Finalize, but we need to override it again, to make it
// final (so that non-Java types cannot override it either).
needFinalize = true;
needDispatch = false;
// If the base class finalize was optimized away, we need a dispatch call after all.
if(baseFinalize.DeclaringType == typeof(object))
{
needDispatch = true;
}
2005-11-01 17:01:42 +03:00
}
else
2005-11-01 17:01:42 +03:00
{
// One of our base classes already has a finalize method, but it may have been an empty
// method so that the hookup to the real Finalize was optimized away, we need to check
// for that.
if(baseFinalize.DeclaringType == typeof(object))
{
needFinalize = true;
needDispatch = true;
}
2005-11-01 17:01:42 +03:00
}
if(needFinalize &&
!m.IsAbstract && !m.IsNative &&
(!m.IsFinal || classFile.IsFinal) &&
m.Instructions.Length > 0 &&
m.Instructions[0].NormalizedOpCode == NormalizedByteCode.__return)
2005-11-01 17:01:42 +03:00
{
// we've got an empty finalize method, so we don't need to override the real finalizer
// (not having a finalizer makes a huge perf difference)
needFinalize = false;
2005-11-01 17:01:42 +03:00
}
}
if(setNameSig || memberclashtable != null)
{
// TODO we really should make sure that the name we generate doesn't already exist in a
// base class (not in the Java method namespace, but in the CLR method namespace)
name = GenerateUniqueMethodName(name, methods[index]);
if(name != m.Name)
2005-11-01 17:01:42 +03:00
{
setNameSig = true;
2005-11-01 17:01:42 +03:00
}
}
bool needMethodImpl = baseMce != null && (explicitOverride || baseMce.RealName != name) && !needFinalize;
if(unloadableOverrideStub || needMethodImpl)
2005-11-01 17:01:42 +03:00
{
attribs |= MethodAttributes.NewSlot;
2005-11-01 17:01:42 +03:00
}
mb = typeBuilder.DefineMethod(name, attribs, methods[index].ReturnTypeForDefineMethod, methods[index].GetParametersForDefineMethod());
if(unloadableOverrideStub)
2006-12-28 10:46:21 +03:00
{
GenerateUnloadableOverrideStub(wrapper, typeBuilder, baseMce, mb, methods[index].ReturnTypeForDefineMethod, methods[index].GetParametersForDefineMethod());
}
else if(needMethodImpl)
{
// assert that the method we're overriding is in fact virtual and not final!
Debug.Assert(baseMce.GetMethod().IsVirtual && !baseMce.GetMethod().IsFinal);
typeBuilder.DefineMethodOverride(mb, (MethodInfo)baseMce.GetMethod());
}
if(!m.IsStatic && !m.IsAbstract && !m.IsPrivate && baseMce != null && !baseMce.DeclaringType.IsPackageAccessibleFrom(wrapper))
{
// we may have to explicitly override another package accessible abstract method
TypeWrapper btw = baseMce.DeclaringType.BaseTypeWrapper;
while(btw != null)
{
MethodWrapper bmw = btw.GetMethodWrapper(m.Name, m.Signature, true);
if(bmw == null)
{
break;
}
if(bmw.DeclaringType.IsPackageAccessibleFrom(wrapper) && bmw.IsAbstract && !(bmw.IsPublic || bmw.IsProtected))
{
if(bmw != baseMce)
{
typeBuilder.DefineMethodOverride(mb, (MethodInfo)bmw.GetMethod());
}
break;
}
btw = bmw.DeclaringType.BaseTypeWrapper;
}
2006-12-28 10:46:21 +03:00
}
// if we're overriding java.lang.Object.finalize we need to emit a stub to override System.Object.Finalize,
// or if we're subclassing a non-Java class that has a Finalize method, we need a new Finalize override
if(needFinalize)
{
string finalizeName = finalizeClash ? "__<Finalize>" : baseFinalize.Name;
// if the Java class also defines a Finalize() method, we need to name the stub differently
foreach(ClassFile.Method mi in classFile.Methods)
{
if(mi.Name == "Finalize" && mi.Signature == "()V")
{
finalizeName = "__<Finalize>";
break;
}
}
MethodAttributes attr = MethodAttributes.HideBySig | MethodAttributes.Virtual;
// make sure we don't reduce accessibility
attr |= baseFinalize.IsPublic ? MethodAttributes.Public : MethodAttributes.Family;
if(m.IsFinal)
{
attr |= MethodAttributes.Final;
}
finalizeMethod = typeBuilder.DefineMethod(finalizeName, attr, CallingConventions.Standard, typeof(void), Type.EmptyTypes);
if(finalizeName != baseFinalize.Name)
{
typeBuilder.DefineMethodOverride(finalizeMethod, baseFinalize);
}
AttributeHelper.HideFromJava(finalizeMethod);
CodeEmitter ilgen = CodeEmitter.Create(finalizeMethod);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.SkipFinalizer);
CodeEmitterLabel skip = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Brtrue_S, skip);
if(needDispatch)
{
ilgen.BeginExceptionBlock();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Callvirt, mb);
ilgen.BeginCatchBlock(typeof(object));
ilgen.EndExceptionBlock();
}
else
{
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Call, baseFinalize);
}
ilgen.MarkLabel(skip);
ilgen.Emit(OpCodes.Ret);
}
#if STATIC_COMPILER
if(classFile.Methods[index].AnnotationDefault != null)
{
CustomAttributeBuilder cab = new CustomAttributeBuilder(StaticCompiler.GetType("IKVM.Attributes.AnnotationDefaultAttribute").GetConstructor(new Type[] { typeof(object) }), new object[] { classFile.Methods[index].AnnotationDefault });
mb.SetCustomAttribute(cab);
}
#endif // STATIC_COMPILER
}
method = mb;
2006-04-20 11:30:59 +04:00
}
string[] exceptions = m.ExceptionsAttribute;
methods[index].SetDeclaredExceptions(exceptions);
#if STATIC_COMPILER
AttributeHelper.SetThrowsAttribute(method, exceptions);
if(setModifiers || m.IsInternal || (m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0)
2006-04-20 11:30:59 +04:00
{
if(method is ConstructorBuilder)
{
AttributeHelper.SetModifiers((ConstructorBuilder)method, m.Modifiers, m.IsInternal);
}
else
{
AttributeHelper.SetModifiers((MethodBuilder)method, m.Modifiers, m.IsInternal);
}
2006-04-20 11:30:59 +04:00
}
if((m.Modifiers & (Modifiers.Synthetic | Modifiers.Bridge)) != 0
&& (m.IsPublic || m.IsProtected) && wrapper.IsPublic)
2006-04-20 11:30:59 +04:00
{
if(method is ConstructorBuilder)
{
AttributeHelper.SetEditorBrowsableNever((ConstructorBuilder)method);
}
else
{
AttributeHelper.SetEditorBrowsableNever((MethodBuilder)method);
}
// TODO on WHIDBEY apply CompilerGeneratedAttribute
2006-04-20 11:30:59 +04:00
}
if(m.DeprecatedAttribute)
2006-04-20 11:30:59 +04:00
{
AttributeHelper.SetDeprecatedAttribute(method);
2006-04-20 11:30:59 +04:00
}
if(setNameSig)
2006-06-20 18:31:56 +04:00
{
AttributeHelper.SetNameSig(method, m.Name, m.Signature);
}
if(m.GenericSignature != null)
{
AttributeHelper.SetSignatureAttribute(method, m.GenericSignature);
}
#else // STATIC_COMPILER
if(setModifiers)
{
// shut up the compiler
2006-06-20 18:31:56 +04:00
}
#endif // STATIC_COMPILER
return method;
}
finally
{
Profiler.Leave("JavaTypeImpl.GenerateMethod");
2006-06-20 18:31:56 +04:00
}
}
internal static void GenerateUnloadableOverrideStub(DynamicTypeWrapper wrapper, TypeBuilder typeBuilder, MethodWrapper baseMethod, MethodInfo target, Type targetRet, Type[] targetArgs)
{
Debug.Assert(!baseMethod.HasCallerID);
Type stubret = baseMethod.ReturnTypeForDefineMethod;
Type[] stubargs = baseMethod.GetParametersForDefineMethod();
string name = wrapper.GenerateUniqueMethodName(baseMethod.RealName + "/unloadablestub", baseMethod);
MethodBuilder overrideStub = typeBuilder.DefineMethod(name, MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, stubret, stubargs);
AttributeHelper.HideFromJava(overrideStub);
typeBuilder.DefineMethodOverride(overrideStub, (MethodInfo)baseMethod.GetMethod());
CodeEmitter ilgen = CodeEmitter.Create(overrideStub);
ilgen.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < targetArgs.Length; i++)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)(i + 1));
if (targetArgs[i] != stubargs[i])
{
ilgen.Emit(OpCodes.Castclass, targetArgs[i]);
}
}
ilgen.Emit(OpCodes.Callvirt, target);
if (targetRet != stubret)
{
ilgen.Emit(OpCodes.Castclass, stubret);
}
ilgen.Emit(OpCodes.Ret);
2002-12-18 19:00:25 +03:00
}
2003-12-24 14:51:41 +03:00
internal override Type Type
2004-09-05 13:37:58 +04:00
{
get
2003-08-13 19:00:41 +04:00
{
return typeBuilder;
2003-08-13 19:00:41 +04:00
}
}
internal override string GetGenericSignature()
{
Debug.Fail("Unreachable code");
return null;
}
internal override string[] GetEnclosingMethod()
{
Debug.Fail("Unreachable code");
return null;
}
internal override string GetGenericMethodSignature(int index)
{
Debug.Fail("Unreachable code");
return null;
}
internal override string GetGenericFieldSignature(int index)
{
Debug.Fail("Unreachable code");
return null;
}
2003-05-30 16:08:59 +04:00
internal override object[] GetDeclaredAnnotations()
{
Debug.Fail("Unreachable code");
return null;
}
internal override object GetMethodDefaultValue(int index)
{
Debug.Fail("Unreachable code");
return null;
}
internal override object[] GetMethodAnnotations(int index)
{
Debug.Fail("Unreachable code");
return null;
}
internal override object[][] GetParameterAnnotations(int index)
{
Debug.Fail("Unreachable code");
return null;
}
internal override object[] GetFieldAnnotations(int index)
{
Debug.Fail("Unreachable code");
return null;
}
#if STATIC_COMPILER
internal override Annotation Annotation
{
get
2004-09-05 13:37:58 +04:00
{
return annotationBuilder;
2005-06-01 13:49:30 +04:00
}
}
internal override Type EnumType
2005-06-01 13:49:30 +04:00
{
get
2005-06-01 13:49:30 +04:00
{
return enumBuilder;
}
}
#endif // STATIC_COMPILER
}
2004-09-17 13:32:06 +04:00
private sealed class Metadata
{
private string[] genericMetaData;
private object[][] annotations;
2004-09-17 13:32:06 +04:00
private Metadata(string[] genericMetaData, object[][] annotations)
{
this.genericMetaData = genericMetaData;
this.annotations = annotations;
}
internal static Metadata Create(ClassFile classFile)
{
if(classFile.MajorVersion < 49)
{
return null;
}
string[] genericMetaData = null;
object[][] annotations = null;
for(int i = 0; i < classFile.Methods.Length; i++)
{
if(classFile.Methods[i].GenericSignature != null)
{
if(genericMetaData == null)
{
genericMetaData = new string[classFile.Methods.Length + classFile.Fields.Length + 4];
}
genericMetaData[i + 4] = classFile.Methods[i].GenericSignature;
2005-06-01 13:49:30 +04:00
}
if(classFile.Methods[i].Annotations != null)
2003-05-30 16:08:59 +04:00
{
if(annotations == null)
2005-02-02 18:11:26 +03:00
{
annotations = new object[5][];
2005-02-02 18:11:26 +03:00
}
if(annotations[1] == null)
2005-02-02 18:11:26 +03:00
{
annotations[1] = new object[classFile.Methods.Length];
2005-02-02 18:11:26 +03:00
}
annotations[1][i] = classFile.Methods[i].Annotations;
2005-06-01 13:49:30 +04:00
}
if(classFile.Methods[i].ParameterAnnotations != null)
2005-06-01 13:49:30 +04:00
{
if(annotations == null)
{
annotations = new object[5][];
}
if(annotations[2] == null)
{
annotations[2] = new object[classFile.Methods.Length];
}
annotations[2][i] = classFile.Methods[i].ParameterAnnotations;
2005-06-01 13:49:30 +04:00
}
if(classFile.Methods[i].AnnotationDefault != null)
2005-06-01 13:49:30 +04:00
{
if(annotations == null)
{
annotations = new object[5][];
}
if(annotations[3] == null)
{
annotations[3] = new object[classFile.Methods.Length];
}
annotations[3][i] = classFile.Methods[i].AnnotationDefault;
2003-05-30 16:08:59 +04:00
}
}
for(int i = 0; i < classFile.Fields.Length; i++)
{
if(classFile.Fields[i].GenericSignature != null)
2003-05-30 16:08:59 +04:00
{
if(genericMetaData == null)
{
genericMetaData = new string[classFile.Methods.Length + classFile.Fields.Length + 4];
}
genericMetaData[i + 4 + classFile.Methods.Length] = classFile.Fields[i].GenericSignature;
2003-05-30 16:08:59 +04:00
}
if(classFile.Fields[i].Annotations != null)
2003-05-30 16:08:59 +04:00
{
if(annotations == null)
2005-02-02 18:11:26 +03:00
{
annotations = new object[5][];
2003-08-01 16:12:08 +04:00
}
if(annotations[4] == null)
{
annotations[4] = new object[classFile.Fields.Length][];
}
annotations[4][i] = classFile.Fields[i].Annotations;
2003-05-30 16:08:59 +04:00
}
}
if(classFile.EnclosingMethod != null)
{
if(genericMetaData == null)
2005-06-01 13:49:30 +04:00
{
genericMetaData = new string[classFile.Methods.Length + classFile.Fields.Length + 4];
}
genericMetaData[0] = classFile.EnclosingMethod[0];
genericMetaData[1] = classFile.EnclosingMethod[1];
genericMetaData[2] = classFile.EnclosingMethod[2];
}
if(classFile.GenericSignature != null)
{
if(genericMetaData == null)
{
genericMetaData = new string[classFile.Methods.Length + classFile.Fields.Length + 4];
2005-06-01 13:49:30 +04:00
}
genericMetaData[3] = classFile.GenericSignature;
}
if(classFile.Annotations != null)
{
if(annotations == null)
2005-06-01 13:49:30 +04:00
{
annotations = new object[5][];
2005-06-01 13:49:30 +04:00
}
annotations[0] = classFile.Annotations;
}
if(genericMetaData != null || annotations != null)
{
return new Metadata(genericMetaData, annotations);
}
return null;
}
internal static string GetGenericSignature(Metadata m)
{
if(m != null && m.genericMetaData != null)
{
return m.genericMetaData[3];
}
return null;
}
internal static string[] GetEnclosingMethod(Metadata m)
{
if(m != null && m.genericMetaData != null && m.genericMetaData[0] != null)
{
return new string[] { m.genericMetaData[0], m.genericMetaData[1], m.genericMetaData[2] };
}
return null;
}
internal static string GetGenericMethodSignature(Metadata m, int index)
{
if(m != null && m.genericMetaData != null)
{
return m.genericMetaData[index + 4];
}
return null;
}
// note that the caller is responsible for computing the correct index (field index + method count)
internal static string GetGenericFieldSignature(Metadata m, int index)
{
if(m != null && m.genericMetaData != null)
{
return m.genericMetaData[index + 4];
}
return null;
}
internal static object[] GetAnnotations(Metadata m)
{
if(m != null && m.annotations != null)
{
return m.annotations[0];
}
return null;
}
internal static object[] GetMethodAnnotations(Metadata m, int index)
{
if(m != null && m.annotations != null && m.annotations[1] != null)
{
return (object[])m.annotations[1][index];
}
return null;
}
internal static object[][] GetMethodParameterAnnotations(Metadata m, int index)
{
if(m != null && m.annotations != null && m.annotations[2] != null)
{
return (object[][])m.annotations[2][index];
}
return null;
}
internal static object GetMethodDefaultValue(Metadata m, int index)
{
if(m != null && m.annotations != null && m.annotations[3] != null)
{
return m.annotations[3][index];
}
return null;
}
// note that unlike GetGenericFieldSignature, the index is simply the field index
internal static object[] GetFieldAnnotations(Metadata m, int index)
{
if(m != null && m.annotations != null && m.annotations[4] != null)
{
return (object[])m.annotations[4][index];
2004-09-27 14:17:34 +04:00
}
return null;
}
}
private sealed class FinishedTypeImpl : DynamicImpl
{
private Type type;
private TypeWrapper[] innerclasses;
private TypeWrapper declaringTypeWrapper;
private Modifiers reflectiveModifiers;
private MethodInfo clinitMethod;
private Metadata metadata;
#if STATIC_COMPILER
private Annotation annotationBuilder;
private TypeBuilder enumBuilder;
#endif
internal FinishedTypeImpl(Type type, TypeWrapper[] innerclasses, TypeWrapper declaringTypeWrapper, Modifiers reflectiveModifiers, Metadata metadata
#if STATIC_COMPILER
, Annotation annotationBuilder
, TypeBuilder enumBuilder
#endif
)
{
this.type = type;
this.innerclasses = innerclasses;
this.declaringTypeWrapper = declaringTypeWrapper;
this.reflectiveModifiers = reflectiveModifiers;
this.clinitMethod = type.GetMethod("__<clinit>", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
this.metadata = metadata;
#if STATIC_COMPILER
this.annotationBuilder = annotationBuilder;
this.enumBuilder = enumBuilder;
#endif
2003-05-30 16:08:59 +04:00
}
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] InnerClasses
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// TODO compute the innerclasses lazily (and fix JavaTypeImpl to not always compute them)
return innerclasses;
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
// TODO compute lazily (and fix JavaTypeImpl to not always compute it)
return declaringTypeWrapper;
2005-06-01 13:49:30 +04:00
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2004-08-17 13:05:21 +04:00
{
return reflectiveModifiers;
2004-08-17 13:05:21 +04:00
}
2003-02-18 12:30:34 +03:00
}
internal override Type Type
2004-08-17 13:05:21 +04:00
{
get
2004-08-17 13:05:21 +04:00
{
return type;
2004-08-17 13:05:21 +04:00
}
}
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
2004-08-17 13:05:21 +04:00
{
if(clinitMethod != null)
2004-08-17 13:05:21 +04:00
{
ilgen.Emit(OpCodes.Call, clinitMethod);
2004-08-17 13:05:21 +04:00
}
}
internal override DynamicImpl Finish()
{
return this;
}
internal override MethodBase LinkMethod(MethodWrapper mw)
{
// we should never be called, because all methods on a finished type are already linked
Debug.Assert(false);
return mw.GetMethod();
}
internal override FieldInfo LinkField(FieldWrapper fw)
{
// we should never be called, because all fields on a finished type are already linked
Debug.Assert(false);
return fw.GetField();
}
internal override string GetGenericSignature()
{
return Metadata.GetGenericSignature(metadata);
}
internal override string[] GetEnclosingMethod()
{
return Metadata.GetEnclosingMethod(metadata);
}
internal override string GetGenericMethodSignature(int index)
{
return Metadata.GetGenericMethodSignature(metadata, index);
}
// note that the caller is responsible for computing the correct index (field index + method count)
internal override string GetGenericFieldSignature(int index)
{
return Metadata.GetGenericFieldSignature(metadata, index);
}
internal override object[] GetDeclaredAnnotations()
{
return Metadata.GetAnnotations(metadata);
}
internal override object GetMethodDefaultValue(int index)
{
return Metadata.GetMethodDefaultValue(metadata, index);
}
internal override object[] GetMethodAnnotations(int index)
{
return Metadata.GetMethodAnnotations(metadata, index);
}
internal override object[][] GetParameterAnnotations(int index)
{
return Metadata.GetMethodParameterAnnotations(metadata, index);
}
internal override object[] GetFieldAnnotations(int index)
{
return Metadata.GetFieldAnnotations(metadata, index);
}
#if STATIC_COMPILER
internal override Annotation Annotation
2002-12-29 19:27:00 +03:00
{
get
{
return annotationBuilder;
}
2004-08-17 13:05:21 +04:00
}
internal override Type EnumType
2004-08-17 13:05:21 +04:00
{
get
2002-12-18 19:00:25 +03:00
{
return enumBuilder;
2005-05-31 12:57:24 +04:00
}
2005-06-01 13:49:30 +04:00
}
#endif // STATIC_COMPILER
}
2005-06-01 13:49:30 +04:00
internal sealed class FinishContext
{
private readonly ClassFile classFile;
private readonly DynamicTypeWrapper wrapper;
private readonly TypeBuilder typeBuilder;
private FieldInfo classObjectField;
private TypeBuilder typeCallerID;
private FieldInfo callerIDField;
private List<System.Threading.ThreadStart> postFinishProcs;
internal FinishContext(ClassFile classFile, DynamicTypeWrapper wrapper, TypeBuilder typeBuilder)
2006-08-15 12:50:43 +04:00
{
this.classFile = classFile;
this.wrapper = wrapper;
this.typeBuilder = typeBuilder;
2006-08-15 12:50:43 +04:00
}
internal FieldInfo ClassObjectField
2005-06-01 13:49:30 +04:00
{
get
2003-05-30 16:08:59 +04:00
{
if (classObjectField == null)
2005-06-01 13:49:30 +04:00
{
classObjectField = typeBuilder.DefineField("__<classObject>", typeof(object), FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.SpecialName);
2005-06-01 13:49:30 +04:00
}
return classObjectField;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
}
internal FieldInfo CallerIDField
2006-07-24 15:47:55 +04:00
{
get
2006-07-24 15:47:55 +04:00
{
if (callerIDField == null)
2006-07-24 15:47:55 +04:00
{
TypeWrapper tw = CoreClasses.ikvm.@internal.CallerID.Wrapper;
callerIDField = typeBuilder.DefineField("__<callerID>", tw.TypeAsSignatureType, FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly | FieldAttributes.SpecialName);
2006-07-24 15:47:55 +04:00
}
return callerIDField;
2006-07-24 15:47:55 +04:00
}
}
internal void RegisterPostFinishProc(System.Threading.ThreadStart proc)
{
if (postFinishProcs == null)
{
postFinishProcs = new List<System.Threading.ThreadStart>();
}
postFinishProcs.Add(proc);
}
internal Type FinishImpl()
2005-06-01 13:49:30 +04:00
{
MethodWrapper[] methods = wrapper.GetMethods();
FieldWrapper[] fields = wrapper.GetFields();
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER
wrapper.FinishGhost(typeBuilder, methods);
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
// if we're not abstract make sure we don't inherit any abstract methods
if (!wrapper.IsAbstract)
{
TypeWrapper parent = wrapper.BaseTypeWrapper;
// if parent is not abstract, the .NET implementation will never have abstract methods (only
// stubs that throw AbstractMethodError)
// NOTE interfaces are supposed to be abstract, but the VM doesn't enforce this, so
// we have to check for a null parent (interfaces have no parent).
while (parent != null && parent.IsAbstract)
2004-08-17 13:05:21 +04:00
{
foreach (MethodWrapper mw in parent.GetMethods())
2004-08-17 13:05:21 +04:00
{
MethodInfo mi = mw.GetMethod() as MethodInfo;
if (mi != null && mi.IsAbstract && !mi.DeclaringType.IsInterface)
{
bool needStub = false;
bool needRename = false;
if (mw.IsPublic || mw.IsProtected)
{
MethodWrapper fmw = wrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
while (fmw != mw && (fmw.IsStatic || fmw.IsPrivate))
{
needRename = true;
fmw = fmw.DeclaringType.BaseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
}
if (fmw == mw && fmw.DeclaringType != wrapper)
{
needStub = true;
}
}
else
{
MethodWrapper fmw = wrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
while (fmw != mw && (fmw.IsStatic || fmw.IsPrivate || !fmw.DeclaringType.IsPackageAccessibleFrom(mw.DeclaringType)))
{
needRename = true;
fmw = fmw.DeclaringType.BaseTypeWrapper.GetMethodWrapper(mw.Name, mw.Signature, true);
}
if (fmw == mw && fmw.DeclaringType != wrapper)
{
needStub = true;
}
}
if (needStub)
{
// NOTE in Sun's JRE 1.4.1 this method cannot be overridden by subclasses,
// but I think this is a bug, so we'll support it anyway.
string name = mi.Name;
MethodAttributes attr = mi.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot);
if (needRename)
{
name = "__<>" + name + "/" + mi.DeclaringType.FullName;
attr = MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot;
}
MethodBuilder mb = typeBuilder.DefineMethod(name, attr, CallingConventions.Standard, mw.ReturnTypeForDefineMethod, mw.GetParametersForDefineMethod());
if (needRename)
{
typeBuilder.DefineMethodOverride(mb, mi);
}
AttributeHelper.HideFromJava(mb);
EmitHelper.Throw(CodeEmitter.Create(mb), "java.lang.AbstractMethodError", mw.DeclaringType.Name + "." + mw.Name + mw.Signature);
}
}
2004-08-17 13:05:21 +04:00
}
parent = parent.BaseTypeWrapper;
2004-08-17 13:05:21 +04:00
}
}
Hashtable invokespecialstubcache = new Hashtable();
bool basehasclinit = wrapper.BaseTypeWrapper != null && wrapper.BaseTypeWrapper.HasStaticInitializer;
int clinitIndex = -1;
bool hasConstructor = false;
for (int i = 0; i < classFile.Methods.Length; i++)
{
ClassFile.Method m = classFile.Methods[i];
MethodBase mb = methods[i].GetMethod();
if (mb is ConstructorBuilder)
2003-05-30 16:08:59 +04:00
{
if (m.IsClassInitializer)
{
// we handle the <clinit> after we've done the other methods,
// to make it easier to inject code needed by the other methods
clinitIndex = i;
continue;
}
else
{
hasConstructor = true;
}
CodeEmitter ilGenerator = CodeEmitter.Create((ConstructorBuilder)mb);
CompileConstructorBody(this, ilGenerator, i, invokespecialstubcache);
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-05-30 16:08:59 +04:00
{
if (m.IsAbstract)
2002-12-18 19:00:25 +03:00
{
bool stub = false;
if (!classFile.IsAbstract)
2005-06-01 13:49:30 +04:00
{
// NOTE in the JVM it is apparently legal for a non-abstract class to have abstract methods, but
// the CLR doens't allow this, so we have to emit a method that throws an AbstractMethodError
stub = true;
2005-06-01 13:49:30 +04:00
}
else if (classFile.IsPublic && !classFile.IsFinal && !(m.IsPublic || m.IsProtected))
2005-06-01 13:49:30 +04:00
{
// We have an abstract package accessible method in our public class. To allow a class in another
// assembly to subclass this class, we must fake the abstractness of this method.
stub = true;
2005-06-01 13:49:30 +04:00
}
if (stub)
2002-12-18 19:00:25 +03:00
{
CodeEmitter ilGenerator = CodeEmitter.Create((MethodBuilder)mb);
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
EmitHelper.Throw(ilGenerator, "java.lang.AbstractMethodError", classFile.Name + "." + m.Name + m.Signature);
2002-12-18 19:00:25 +03:00
}
}
else if (m.IsNative)
2005-06-01 13:49:30 +04:00
{
if ((mb.Attributes & MethodAttributes.PinvokeImpl) != 0)
2005-09-08 21:44:35 +04:00
{
continue;
2005-09-08 21:44:35 +04:00
}
Profiler.Enter("JavaTypeImpl.Finish.Native");
try
{
CodeEmitter ilGenerator = CodeEmitter.Create((MethodBuilder)mb);
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
#if STATIC_COMPILER
// do we have a native implementation in map.xml?
if (wrapper.EmitMapXmlMethodBody(ilGenerator, classFile, m))
{
continue;
}
#endif
// see if there exists a IKVM.NativeCode class for this type
Type nativeCodeType = null;
2006-09-12 13:57:36 +04:00
#if STATIC_COMPILER
nativeCodeType = StaticCompiler.GetType("IKVM.NativeCode." + classFile.Name.Replace('$', '+'), false);
2006-09-12 13:57:36 +04:00
#endif
MethodInfo nativeMethod = null;
TypeWrapper[] args = methods[i].GetParameters();
if (nativeCodeType != null)
2004-12-02 11:43:05 +03:00
{
TypeWrapper[] nargs = args;
if (!m.IsStatic)
{
nargs = new TypeWrapper[args.Length + 1];
args.CopyTo(nargs, 1);
nargs[0] = this.wrapper;
}
MethodInfo[] nativeCodeTypeMethods = nativeCodeType.GetMethods(BindingFlags.Static | BindingFlags.Public);
foreach (MethodInfo method in nativeCodeTypeMethods)
{
ParameterInfo[] param = method.GetParameters();
TypeWrapper[] match = new TypeWrapper[param.Length];
for (int j = 0; j < param.Length; j++)
{
match[j] = ClassLoaderWrapper.GetWrapperFromType(param[j].ParameterType);
}
if (m.Name == method.Name && IsCompatibleArgList(nargs, match))
{
// TODO instead of taking the first matching method, we should find the best one
nativeMethod = method;
break;
}
}
2004-12-02 11:43:05 +03:00
}
if (nativeMethod != null)
2005-06-01 13:49:30 +04:00
{
int add = 0;
if (!m.IsStatic)
2005-06-01 13:49:30 +04:00
{
ilGenerator.Emit(OpCodes.Ldarg_0);
add = 1;
}
for (int j = 0; j < args.Length; j++)
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
}
ilGenerator.Emit(OpCodes.Call, nativeMethod);
TypeWrapper retTypeWrapper = methods[i].ReturnType;
if (!retTypeWrapper.TypeAsTBD.Equals(nativeMethod.ReturnType) && !retTypeWrapper.IsGhost)
{
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD);
2005-06-01 13:49:30 +04:00
}
ilGenerator.Emit(OpCodes.Ret);
2005-06-01 13:49:30 +04:00
}
else
{
if (wrapper.classLoader.NoJNI)
2005-06-01 13:49:30 +04:00
{
// since NoJniStubs can only be set when we're statically compiling, it is safe to use the "compiler" trace switch
Tracer.Warning(Tracer.Compiler, "Native method not implemented: {0}.{1}.{2}", classFile.Name, m.Name, m.Signature);
EmitHelper.Throw(ilGenerator, "java.lang.UnsatisfiedLinkError", "Native method not implemented (compiled with -nojni): " + classFile.Name + "." + m.Name + m.Signature);
}
else
{
if (JVM.IsSaveDebugImage)
{
#if !STATIC_COMPILER
JniProxyBuilder.Generate(this, ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args);
#endif // !STATIC_COMPILER
}
else
{
JniBuilder.Generate(this, ilGenerator, wrapper, methods[i], typeBuilder, classFile, m, args, false);
}
2005-06-01 13:49:30 +04:00
}
}
2004-12-02 11:43:05 +03:00
}
finally
2004-03-16 20:10:09 +03:00
{
Profiler.Leave("JavaTypeImpl.Finish.Native");
2004-03-16 20:10:09 +03:00
}
}
else
{
MethodBuilder mbld = (MethodBuilder)mb;
CodeEmitter ilGenerator = CodeEmitter.Create(mbld);
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
#if STATIC_COMPILER
if (wrapper.EmitMapXmlMethodBody(ilGenerator, classFile, m))
2005-08-05 12:40:54 +04:00
{
continue;
2005-08-05 12:40:54 +04:00
}
#endif // STATIC_COMPILER
LineNumberTableAttribute.LineNumberWriter lineNumberTable = null;
bool nonleaf = false;
Compiler.Compile(this, wrapper, methods[i], classFile, m, ilGenerator, ref nonleaf, invokespecialstubcache, ref lineNumberTable);
if (nonleaf)
2004-03-16 20:10:09 +03:00
{
mbld.SetImplementationFlags(mbld.GetMethodImplementationFlags() | MethodImplAttributes.NoInlining);
2004-03-16 20:10:09 +03:00
}
if (lineNumberTable != null)
2004-03-16 20:10:09 +03:00
{
#if STATIC_COMPILER
AttributeHelper.SetLineNumberTable(methods[i].GetMethod(), lineNumberTable);
#else // STATIC_COMPILER
if (wrapper.lineNumberTables == null)
{
wrapper.lineNumberTables = new byte[methods.Length][];
}
wrapper.lineNumberTables[i] = lineNumberTable.ToArray();
#endif // STATIC_COMPILER
2004-03-16 20:10:09 +03:00
}
}
}
}
if (clinitIndex != -1 || (basehasclinit && !classFile.IsInterface) || classFile.HasInitializedFields || callerIDField != null)
{
ConstructorBuilder cb;
if (clinitIndex != -1)
{
cb = (ConstructorBuilder)methods[clinitIndex].GetMethod();
}
else
{
cb = JavaTypeImpl.DefineClassInitializer(typeBuilder);
AttributeHelper.HideFromJava(cb);
}
CodeEmitter ilGenerator = CodeEmitter.Create(cb);
// HACK we start out by emitting the users code, because that may trigger the creation of caller id infrastructure
CodeEmitterLabel label1 = null;
if (clinitIndex != -1)
{
label1 = ilGenerator.DefineLabel();
CodeEmitterLabel label2 = ilGenerator.DefineLabel();
ilGenerator.Emit(OpCodes.Br, label2);
ilGenerator.MarkLabel(label1);
CompileConstructorBody(this, ilGenerator, clinitIndex, invokespecialstubcache);
ilGenerator.MarkLabel(label2);
}
// before we call the base class initializer, we need to set the non-final static ConstantValue fields
EmitConstantValueInitialization(fields, ilGenerator);
EmitCallerIDInitialization(ilGenerator);
if (basehasclinit)
{
wrapper.BaseTypeWrapper.EmitRunClassConstructor(ilGenerator);
}
if (clinitIndex != -1)
{
ilGenerator.Emit(OpCodes.Br, label1);
}
else
{
ilGenerator.Emit(OpCodes.Ret);
}
}
// add all interfaces that we implement (including the magic ones) and handle ghost conversions
ImplementInterfaces(wrapper.Interfaces, new ArrayList());
// NOTE non-final fields aren't allowed in interfaces so we don't have to initialize constant fields
if (!classFile.IsInterface)
{
// if a class has no constructor, we generate one otherwise Ref.Emit will create a default ctor
// and that has several problems:
// - base type may not have an accessible default constructor
// - Ref.Emit uses BaseType.GetConstructors() which may trigger a TypeResolve event
// - we don't want the synthesized constructor to show up in Java
if (!hasConstructor)
{
ConstructorBuilder cb = typeBuilder.DefineConstructor(MethodAttributes.PrivateScope, CallingConventions.Standard, Type.EmptyTypes);
CodeEmitter ilgen = CodeEmitter.Create(cb);
ilgen.Emit(OpCodes.Ldnull);
ilgen.Emit(OpCodes.Throw);
}
// here we loop thru all the interfaces to explicitly implement any methods that we inherit from
// base types that may have a different name from the name in the interface
// (e.g. interface that has an equals() method that should override System.Object.Equals())
// also deals with interface methods that aren't implemented (generate a stub that throws AbstractMethodError)
// and with methods that aren't public (generate a stub that throws IllegalAccessError)
Hashtable doneSet = new Hashtable();
TypeWrapper[] interfaces = wrapper.Interfaces;
for (int i = 0; i < interfaces.Length; i++)
{
interfaces[i].ImplementInterfaceMethodStubs(typeBuilder, wrapper, doneSet);
}
// if any of our base classes has an incomplete interface implementation we need to look through all
// the base class interfaces to see if we've got an implementation now
TypeWrapper baseTypeWrapper = wrapper.BaseTypeWrapper;
while (baseTypeWrapper.HasIncompleteInterfaceImplementation)
{
for (int i = 0; i < baseTypeWrapper.Interfaces.Length; i++)
{
baseTypeWrapper.Interfaces[i].ImplementInterfaceMethodStubs(typeBuilder, wrapper, doneSet);
}
baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper;
}
if (!wrapper.IsAbstract && wrapper.HasUnsupportedAbstractMethods)
{
AddUnsupportedAbstractMethods();
}
foreach (MethodWrapper mw in methods)
{
if (mw.Name != "<init>" && !mw.IsStatic && mw.IsPublic)
{
if (wrapper.BaseTypeWrapper != null && wrapper.BaseTypeWrapper.HasIncompleteInterfaceImplementation)
{
Hashtable hashtable = null;
TypeWrapper tw = wrapper.BaseTypeWrapper;
while (tw.HasIncompleteInterfaceImplementation)
{
foreach (TypeWrapper iface in tw.Interfaces)
{
AddMethodOverride(mw, (MethodBuilder)mw.GetMethod(), iface, mw.Name, mw.Signature, ref hashtable, false);
}
tw = tw.BaseTypeWrapper;
}
}
if (true)
2005-06-01 13:49:30 +04:00
{
Hashtable hashtable = null;
foreach (TypeWrapper iface in wrapper.Interfaces)
2005-06-01 13:49:30 +04:00
{
AddMethodOverride(mw, (MethodBuilder)mw.GetMethod(), iface, mw.Name, mw.Signature, ref hashtable, true);
2005-06-01 13:49:30 +04:00
}
2005-11-01 17:01:42 +03:00
}
2005-06-01 13:49:30 +04:00
}
2003-07-31 16:49:29 +04:00
}
}
2006-05-04 12:09:56 +04:00
#if STATIC_COMPILER
// If we're an interface that has public/protected fields, we create an inner class
// to expose these fields to C# (which stubbornly refuses to see fields in interfaces).
TypeBuilder tbFields = null;
if (classFile.IsInterface && classFile.IsPublic && !wrapper.IsGhost && classFile.Fields.Length > 0)
{
// TODO handle name clash
tbFields = typeBuilder.DefineNestedType("__Fields", TypeAttributes.Class | TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.Abstract);
AttributeHelper.HideFromJava(tbFields);
CodeEmitter ilgenClinit = null;
for (int i = 0; i < classFile.Fields.Length; i++)
2005-05-24 19:18:27 +04:00
{
ClassFile.Field f = classFile.Fields[i];
if (f.ConstantValue != null)
2005-10-01 15:16:11 +04:00
{
FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal;
FieldBuilder fb = tbFields.DefineField(f.Name, fields[i].FieldTypeWrapper.TypeAsSignatureType, attribs);
fb.SetConstant(f.ConstantValue);
2005-06-01 13:49:30 +04:00
}
2006-05-04 12:09:56 +04:00
else
2005-10-01 15:16:11 +04:00
{
FieldAttributes attribs = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly;
FieldBuilder fb = tbFields.DefineField(f.Name, fields[i].FieldTypeWrapper.TypeAsSignatureType, attribs);
if (ilgenClinit == null)
{
ilgenClinit = CodeEmitter.Create(tbFields.DefineTypeInitializer());
}
wrapper.GetFieldWrapper(f.Name, f.Signature).EmitGet(ilgenClinit);
ilgenClinit.Emit(OpCodes.Stsfld, fb);
2005-10-01 15:16:11 +04:00
}
2003-04-26 16:13:02 +04:00
}
if (ilgenClinit != null)
{
ilgenClinit.Emit(OpCodes.Ret);
}
}
// See if there is any additional metadata
wrapper.EmitMapXmlMetadata(typeBuilder, classFile, fields, methods);
#endif // STATIC_COMPILER
for (int i = 0; i < classFile.Methods.Length; i++)
{
ClassFile.Method m = classFile.Methods[i];
MethodBase mb = methods[i].GetMethod();
ParameterBuilder returnParameter = null;
ParameterBuilder[] parameterBuilders = null;
string[] parameterNames = null;
if (wrapper.GetClassLoader().EmitDebugInfo
#if STATIC_COMPILER
|| (classFile.IsPublic && (m.IsPublic || m.IsProtected))
#endif
)
{
parameterNames = new string[methods[i].GetParameters().Length];
GetParameterNamesFromLVT(m, parameterNames);
GetParameterNamesFromSig(m.Signature, parameterNames);
#if STATIC_COMPILER
((AotTypeWrapper)wrapper).GetParameterNamesFromXml(m.Name, m.Signature, parameterNames);
#endif
parameterBuilders = GetParameterBuilders(mb, parameterNames.Length, parameterNames);
}
#if STATIC_COMPILER
if ((m.Modifiers & Modifiers.VarArgs) != 0 && !methods[i].HasCallerID)
{
if (parameterBuilders == null)
{
parameterBuilders = GetParameterBuilders(mb, methods[i].GetParameters().Length, null);
}
if (parameterBuilders.Length > 0)
{
AttributeHelper.SetParamArrayAttribute(parameterBuilders[parameterBuilders.Length - 1]);
}
2006-05-04 12:09:56 +04:00
}
((AotTypeWrapper)wrapper).AddXmlMapParameterAttributes(mb, classFile.Name, m.Name, m.Signature, ref parameterBuilders);
#endif
ConstructorBuilder cb = mb as ConstructorBuilder;
MethodBuilder mBuilder = mb as MethodBuilder;
if (m.Annotations != null)
2006-05-04 12:09:56 +04:00
{
foreach (object[] def in m.Annotations)
{
Annotation annotation = Annotation.Load(wrapper.GetClassLoader(), def);
if (annotation != null)
{
if (cb != null)
{
annotation.Apply(wrapper.GetClassLoader(), cb, def);
}
if (mBuilder != null)
{
annotation.Apply(wrapper.GetClassLoader(), mBuilder, def);
annotation.ApplyReturnValue(wrapper.GetClassLoader(), mBuilder, ref returnParameter, def);
}
}
}
2006-05-04 12:09:56 +04:00
}
if (m.ParameterAnnotations != null)
2006-05-04 12:09:56 +04:00
{
if (parameterBuilders == null)
{
parameterBuilders = GetParameterBuilders(mb, methods[i].GetParameters().Length, null);
}
object[][] defs = m.ParameterAnnotations;
for (int j = 0; j < defs.Length; j++)
{
foreach (object[] def in defs[j])
{
Annotation annotation = Annotation.Load(wrapper.GetClassLoader(), def);
if (annotation != null)
{
annotation.Apply(wrapper.GetClassLoader(), parameterBuilders[j], def);
}
}
}
2006-05-04 12:09:56 +04:00
}
#if STATIC_COMPILER
if (methods[i].HasCallerID)
2006-08-17 17:18:45 +04:00
{
AttributeHelper.SetEditorBrowsableNever((MethodBuilder)mb);
EmitCallerIDStub(methods[i], parameterNames);
2006-08-17 17:18:45 +04:00
}
2006-05-04 12:09:56 +04:00
#endif // STATIC_COMPILER
2003-11-17 15:01:50 +03:00
}
2002-12-18 19:00:25 +03:00
for (int i = 0; i < classFile.Fields.Length; i++)
2005-05-27 16:44:06 +04:00
{
if (classFile.Fields[i].Annotations != null)
2005-06-01 13:49:30 +04:00
{
foreach (object[] def in classFile.Fields[i].Annotations)
{
Annotation annotation = Annotation.Load(wrapper.GetClassLoader(), def);
if (annotation != null)
{
GetterFieldWrapper getter = fields[i] as GetterFieldWrapper;
if (getter != null)
{
annotation.Apply(wrapper.GetClassLoader(), (MethodBuilder)getter.GetGetter(), def);
}
else
{
DynamicPropertyFieldWrapper prop = fields[i] as DynamicPropertyFieldWrapper;
if (prop != null)
{
annotation.Apply(wrapper.GetClassLoader(), prop.GetPropertyBuilder(), def);
}
else
{
annotation.Apply(wrapper.GetClassLoader(), (FieldBuilder)fields[i].GetField(), def);
}
}
}
}
2005-06-01 13:49:30 +04:00
}
2005-05-27 16:44:06 +04:00
}
if (classFile.Annotations != null)
2005-06-01 13:49:30 +04:00
{
foreach (object[] def in classFile.Annotations)
2005-06-01 13:49:30 +04:00
{
Annotation annotation = Annotation.Load(wrapper.GetClassLoader(), def);
if (annotation != null)
{
annotation.Apply(wrapper.GetClassLoader(), typeBuilder, def);
}
2005-06-01 13:49:30 +04:00
}
}
2003-06-18 12:48:00 +04:00
Type type;
Profiler.Enter("TypeBuilder.CreateType");
try
2004-08-17 13:05:21 +04:00
{
type = typeBuilder.CreateType();
if (typeCallerID != null)
2005-06-01 13:49:30 +04:00
{
typeCallerID.CreateType();
2005-06-01 13:49:30 +04:00
}
if (postFinishProcs != null)
{
foreach (System.Threading.ThreadStart proc in postFinishProcs)
{
proc();
}
}
#if STATIC_COMPILER
if (tbFields != null)
2005-06-01 13:49:30 +04:00
{
tbFields.CreateType();
2005-06-01 13:49:30 +04:00
}
if (classFile.IsInterface && !classFile.IsPublic)
2005-06-01 13:49:30 +04:00
{
((DynamicClassLoader)wrapper.classLoader.GetTypeWrapperFactory()).DefineProxyHelper(type);
2005-06-01 13:49:30 +04:00
}
#endif
2004-08-17 13:05:21 +04:00
}
finally
2005-06-01 13:49:30 +04:00
{
Profiler.Leave("TypeBuilder.CreateType");
2005-06-01 13:49:30 +04:00
}
ClassLoaderWrapper.SetWrapperForType(type, wrapper);
#if STATIC_COMPILER
wrapper.FinishGhostStep2();
#endif
BakedTypeCleanupHack.Process(wrapper);
return type;
2002-12-18 19:00:25 +03:00
}
2005-10-01 15:16:11 +04:00
#if !STATIC_COMPILER
2008-06-03 11:13:49 +04:00
internal static class JniProxyBuilder
2006-04-19 19:49:54 +04:00
{
private static ModuleBuilder mod;
private static int count;
2006-12-28 10:46:21 +03:00
static JniProxyBuilder()
2006-12-28 10:46:21 +03:00
{
AssemblyName name = new AssemblyName();
name.Name = "jniproxy";
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(name, JVM.IsSaveDebugImage ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run);
DynamicClassLoader.RegisterForSaveDebug(ab);
mod = ab.DefineDynamicModule("jniproxy.dll", "jniproxy.dll");
CustomAttributeBuilder cab = new CustomAttributeBuilder(JVM.LoadType(typeof(JavaModuleAttribute)).GetConstructor(Type.EmptyTypes), new object[0]);
mod.SetCustomAttribute(cab);
2006-12-28 10:46:21 +03:00
}
internal static void Generate(DynamicTypeWrapper.FinishContext context, CodeEmitter ilGenerator, DynamicTypeWrapper wrapper, MethodWrapper mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, TypeWrapper[] args)
2006-12-28 10:46:21 +03:00
{
TypeBuilder tb = mod.DefineType("__<jni>" + (count++), TypeAttributes.Public | TypeAttributes.Class);
int instance = m.IsStatic ? 0 : 1;
Type[] argTypes = new Type[args.Length + instance + 1];
if (instance != 0)
{
argTypes[0] = typeof(object);
}
for (int i = 0; i < args.Length; i++)
{
// NOTE we take a shortcut here by assuming that all "special" types (i.e. ghost or value types)
// are public and so we can get away with replacing all other types with object.
argTypes[i + instance] = (args[i].IsPrimitive || args[i].IsGhost || args[i].IsNonPrimitiveValueType) ? args[i].TypeAsSignatureType : typeof(object);
}
argTypes[argTypes.Length - 1] = typeof(RuntimeMethodHandle);
Type retType = (mw.ReturnType.IsPrimitive || mw.ReturnType.IsGhost || mw.ReturnType.IsNonPrimitiveValueType) ? mw.ReturnType.TypeAsSignatureType : typeof(object);
MethodBuilder mb = tb.DefineMethod("method", MethodAttributes.Public | MethodAttributes.Static, retType, argTypes);
AttributeHelper.HideFromJava(mb);
JniBuilder.Generate(context, CodeEmitter.Create(mb), wrapper, mw, tb, classFile, m, args, true);
tb.CreateType();
for (int i = 0; i < argTypes.Length - 1; i++)
{
ilGenerator.Emit(OpCodes.Ldarg, (short)i);
}
ilGenerator.Emit(OpCodes.Ldtoken, (MethodInfo)mw.GetMethod());
ilGenerator.Emit(OpCodes.Call, mb);
if (!mw.ReturnType.IsPrimitive && !mw.ReturnType.IsGhost && !mw.ReturnType.IsNonPrimitiveValueType)
{
ilGenerator.Emit(OpCodes.Castclass, mw.ReturnType.TypeAsSignatureType);
}
ilGenerator.Emit(OpCodes.Ret);
2006-12-28 10:46:21 +03:00
}
}
#endif // !STATIC_COMPILER
2005-11-01 17:01:42 +03:00
2008-06-03 11:13:49 +04:00
private static class JniBuilder
2005-11-01 17:01:42 +03:00
{
#if STATIC_COMPILER
private static readonly Type localRefStructType = StaticCompiler.GetType("IKVM.Runtime.JNI+Frame");
#elif FIRST_PASS
private static readonly Type localRefStructType = null;
#else
private static readonly Type localRefStructType = JVM.LoadType(typeof(IKVM.Runtime.JNI.Frame));
#endif
private static readonly MethodInfo jniFuncPtrMethod = localRefStructType.GetMethod("GetFuncPtr");
private static readonly MethodInfo enterLocalRefStruct = localRefStructType.GetMethod("Enter");
private static readonly MethodInfo leaveLocalRefStruct = localRefStructType.GetMethod("Leave");
private static readonly MethodInfo makeLocalRef = localRefStructType.GetMethod("MakeLocalRef");
private static readonly MethodInfo unwrapLocalRef = localRefStructType.GetMethod("UnwrapLocalRef");
private static readonly MethodInfo writeLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }, null);
private static readonly MethodInfo monitorEnter = typeof(System.Threading.Monitor).GetMethod("Enter", new Type[] { typeof(object) });
private static readonly MethodInfo monitorExit = typeof(System.Threading.Monitor).GetMethod("Exit", new Type[] { typeof(object) });
2005-11-01 17:01:42 +03:00
internal static void Generate(DynamicTypeWrapper.FinishContext context, CodeEmitter ilGenerator, DynamicTypeWrapper wrapper, MethodWrapper mw, TypeBuilder typeBuilder, ClassFile classFile, ClassFile.Method m, TypeWrapper[] args, bool thruProxy)
2005-11-01 17:01:42 +03:00
{
LocalBuilder syncObject = null;
FieldInfo classObjectField;
if (thruProxy)
2005-11-01 17:01:42 +03:00
{
classObjectField = typeBuilder.DefineField("__<classObject>", typeof(object), FieldAttributes.Static | FieldAttributes.Private | FieldAttributes.SpecialName);
2005-11-01 17:01:42 +03:00
}
else
2005-11-01 17:01:42 +03:00
{
classObjectField = context.ClassObjectField;
2005-11-01 17:01:42 +03:00
}
if (m.IsSynchronized && m.IsStatic)
2005-11-01 17:01:42 +03:00
{
ilGenerator.Emit(OpCodes.Ldsfld, classObjectField);
CodeEmitterLabel label = ilGenerator.DefineLabel();
ilGenerator.Emit(OpCodes.Brtrue_S, label);
ilGenerator.Emit(OpCodes.Ldtoken, wrapper.TypeAsTBD);
ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.GetClassFromTypeHandle);
ilGenerator.Emit(OpCodes.Stsfld, classObjectField);
ilGenerator.MarkLabel(label);
ilGenerator.Emit(OpCodes.Ldsfld, classObjectField);
ilGenerator.Emit(OpCodes.Dup);
syncObject = ilGenerator.DeclareLocal(typeof(object));
ilGenerator.Emit(OpCodes.Stloc, syncObject);
ilGenerator.Emit(OpCodes.Call, monitorEnter);
ilGenerator.BeginExceptionBlock();
}
string sig = m.Signature.Replace('.', '/');
// TODO use/unify JNI.METHOD_PTR_FIELD_PREFIX
FieldBuilder methodPtr = typeBuilder.DefineField("__<jniptr>" + m.Name + sig, typeof(IntPtr), FieldAttributes.Static | FieldAttributes.PrivateScope);
LocalBuilder localRefStruct = ilGenerator.DeclareLocal(localRefStructType);
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
ilGenerator.Emit(OpCodes.Initobj, localRefStructType);
ilGenerator.Emit(OpCodes.Ldsfld, methodPtr);
CodeEmitterLabel oklabel = ilGenerator.DefineLabel();
ilGenerator.Emit(OpCodes.Brtrue, oklabel);
if (thruProxy)
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(args.Length + (mw.IsStatic ? 0 : 1)));
}
else
{
ilGenerator.Emit(OpCodes.Ldtoken, (MethodInfo)mw.GetMethod());
}
ilGenerator.Emit(OpCodes.Ldstr, classFile.Name.Replace('.', '/'));
ilGenerator.Emit(OpCodes.Ldstr, m.Name);
ilGenerator.Emit(OpCodes.Ldstr, sig);
ilGenerator.Emit(OpCodes.Call, jniFuncPtrMethod);
ilGenerator.Emit(OpCodes.Stsfld, methodPtr);
ilGenerator.MarkLabel(oklabel);
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
if (thruProxy)
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(args.Length + (mw.IsStatic ? 0 : 1)));
}
else
{
ilGenerator.Emit(OpCodes.Ldtoken, (MethodInfo)mw.GetMethod());
}
ilGenerator.Emit(OpCodes.Call, enterLocalRefStruct);
LocalBuilder jnienv = ilGenerator.DeclareLocal(typeof(IntPtr));
ilGenerator.Emit(OpCodes.Stloc, jnienv);
ilGenerator.BeginExceptionBlock();
TypeWrapper retTypeWrapper = mw.ReturnType;
if (!retTypeWrapper.IsUnloadable && !retTypeWrapper.IsPrimitive)
{
// this one is for use after we return from "calli"
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
}
ilGenerator.Emit(OpCodes.Ldloc, jnienv);
Type[] modargs = new Type[args.Length + 2];
modargs[0] = typeof(IntPtr);
modargs[1] = typeof(IntPtr);
for (int i = 0; i < args.Length; i++)
{
modargs[i + 2] = args[i].TypeAsSignatureType;
}
int add = 0;
if (!m.IsStatic)
{
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Call, makeLocalRef);
add = 1;
}
else
{
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
ilGenerator.Emit(OpCodes.Ldsfld, classObjectField);
CodeEmitterLabel label = ilGenerator.DefineLabel();
ilGenerator.Emit(OpCodes.Brtrue_S, label);
ilGenerator.Emit(OpCodes.Ldtoken, wrapper.TypeAsTBD);
ilGenerator.Emit(OpCodes.Call, ByteCodeHelperMethods.GetClassFromTypeHandle);
ilGenerator.Emit(OpCodes.Stsfld, classObjectField);
ilGenerator.MarkLabel(label);
ilGenerator.Emit(OpCodes.Ldsfld, classObjectField);
ilGenerator.Emit(OpCodes.Call, makeLocalRef);
}
for (int j = 0; j < args.Length; j++)
{
if (args[j].IsUnloadable || !args[j].IsPrimitive)
2005-11-01 17:01:42 +03:00
{
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
if (!args[j].IsUnloadable && args[j].IsNonPrimitiveValueType)
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
args[j].EmitBox(ilGenerator);
}
else if (!args[j].IsUnloadable && args[j].IsGhost)
{
ilGenerator.Emit(OpCodes.Ldarga_S, (byte)(j + add));
ilGenerator.Emit(OpCodes.Ldfld, args[j].GhostRefField);
}
else
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
}
ilGenerator.Emit(OpCodes.Call, makeLocalRef);
modargs[j + 2] = typeof(IntPtr);
2005-11-01 17:01:42 +03:00
}
else
2005-11-01 17:01:42 +03:00
{
ilGenerator.Emit(OpCodes.Ldarg_S, (byte)(j + add));
2005-11-01 17:01:42 +03:00
}
}
ilGenerator.Emit(OpCodes.Ldsfld, methodPtr);
Type realRetType;
if (retTypeWrapper == PrimitiveTypeWrapper.BOOLEAN)
2005-11-01 17:01:42 +03:00
{
realRetType = typeof(byte);
}
else if (retTypeWrapper.IsPrimitive)
{
realRetType = retTypeWrapper.TypeAsSignatureType;
}
else
{
realRetType = typeof(IntPtr);
}
ilGenerator.EmitCalli(OpCodes.Calli, System.Runtime.InteropServices.CallingConvention.StdCall, realRetType, modargs);
LocalBuilder retValue = null;
if (retTypeWrapper != PrimitiveTypeWrapper.VOID)
{
if (!retTypeWrapper.IsUnloadable && !retTypeWrapper.IsPrimitive)
2005-11-01 17:01:42 +03:00
{
ilGenerator.Emit(OpCodes.Call, unwrapLocalRef);
if (retTypeWrapper.IsNonPrimitiveValueType)
{
retTypeWrapper.EmitUnbox(ilGenerator);
}
else if (retTypeWrapper.IsGhost)
{
LocalBuilder ghost = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
LocalBuilder obj = ilGenerator.DeclareLocal(typeof(object));
ilGenerator.Emit(OpCodes.Stloc, obj);
ilGenerator.Emit(OpCodes.Ldloca, ghost);
ilGenerator.Emit(OpCodes.Ldloc, obj);
ilGenerator.Emit(OpCodes.Stfld, retTypeWrapper.GhostRefField);
ilGenerator.Emit(OpCodes.Ldloc, ghost);
}
else
{
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsTBD);
}
2005-11-01 17:01:42 +03:00
}
retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Stloc, retValue);
2005-11-01 17:01:42 +03:00
}
ilGenerator.BeginCatchBlock(typeof(object));
ilGenerator.EmitWriteLine("*** exception in native code ***");
ilGenerator.Emit(OpCodes.Call, writeLine);
ilGenerator.Emit(OpCodes.Rethrow);
ilGenerator.BeginFinallyBlock();
ilGenerator.Emit(OpCodes.Ldloca, localRefStruct);
ilGenerator.Emit(OpCodes.Call, leaveLocalRefStruct);
ilGenerator.EndExceptionBlock();
if (m.IsSynchronized && m.IsStatic)
2005-11-01 17:01:42 +03:00
{
ilGenerator.BeginFinallyBlock();
ilGenerator.Emit(OpCodes.Ldloc, syncObject);
ilGenerator.Emit(OpCodes.Call, monitorExit);
ilGenerator.EndExceptionBlock();
2005-11-01 17:01:42 +03:00
}
if (retTypeWrapper != PrimitiveTypeWrapper.VOID)
2005-11-01 17:01:42 +03:00
{
ilGenerator.Emit(OpCodes.Ldloc, retValue);
2005-11-01 17:01:42 +03:00
}
ilGenerator.Emit(OpCodes.Ret);
2005-11-01 17:01:42 +03:00
}
}
2008-06-03 11:13:49 +04:00
private static class TraceHelper
{
#if STATIC_COMPILER
private readonly static MethodInfo methodIsTracedMethod = typeof(Tracer).GetMethod("IsTracedMethod");
#endif
private readonly static MethodInfo methodMethodInfo = typeof(Tracer).GetMethod("MethodInfo");
internal static void EmitMethodTrace(CodeEmitter ilgen, string tracemessage)
2005-11-01 17:01:42 +03:00
{
if (Tracer.IsTracedMethod(tracemessage))
2005-11-01 17:01:42 +03:00
{
CodeEmitterLabel label = ilgen.DefineLabel();
#if STATIC_COMPILER
// TODO this should be a boolean field test instead of a call to Tracer.IsTracedMessage
ilgen.Emit(OpCodes.Ldstr, tracemessage);
ilgen.Emit(OpCodes.Call, methodIsTracedMethod);
ilgen.Emit(OpCodes.Brfalse_S, label);
#endif
ilgen.Emit(OpCodes.Ldstr, tracemessage);
ilgen.Emit(OpCodes.Call, methodMethodInfo);
ilgen.MarkLabel(label);
2005-11-01 17:01:42 +03:00
}
}
}
#if STATIC_COMPILER
private void EmitCallerIDStub(MethodWrapper mw, string[] parameterNames)
{
Type[] p = mw.GetParametersForDefineMethod();
Type[] parameterTypes = new Type[p.Length - 1];
for (int i = 0; i < parameterTypes.Length; i++)
2005-11-01 17:01:42 +03:00
{
parameterTypes[i] = p[i];
2005-11-01 17:01:42 +03:00
}
MethodAttributes attribs = MethodAttributes.HideBySig;
int argcount = parameterTypes.Length;
if (mw.IsStatic)
2005-11-01 17:01:42 +03:00
{
attribs |= MethodAttributes.Static;
}
else
{
argcount++;
}
if (mw.IsPublic)
{
attribs |= MethodAttributes.Public;
}
else if (mw.IsProtected)
{
attribs |= MethodAttributes.FamORAssem;
}
else if (mw.IsPrivate)
{
attribs |= MethodAttributes.Private;
}
else
{
attribs |= MethodAttributes.Assembly;
}
MethodBuilder mb = typeBuilder.DefineMethod(mw.Name, attribs, mw.ReturnTypeForDefineMethod, parameterTypes);
AttributeHelper.HideFromJava(mb);
mb.SetImplementationFlags(MethodImplAttributes.NoInlining);
CodeEmitter ilgen = CodeEmitter.Create(mb);
for (int i = 0; i < argcount; i++)
{
if (parameterNames != null && (mw.IsStatic || i > 0))
2005-11-01 17:01:42 +03:00
{
ParameterBuilder pb = mb.DefineParameter(mw.IsStatic ? i + 1 : i, ParameterAttributes.None, parameterNames[mw.IsStatic ? i : i - 1]);
if (i == argcount - 1 && (mw.Modifiers & Modifiers.VarArgs) != 0)
{
AttributeHelper.SetParamArrayAttribute(pb);
}
2005-11-01 17:01:42 +03:00
}
ilgen.Emit(OpCodes.Ldarg, (short)i);
2005-11-01 17:01:42 +03:00
}
ilgen.Emit(OpCodes.Ldc_I4_1);
ilgen.Emit(OpCodes.Ldc_I4_0);
ilgen.Emit(OpCodes.Newobj, typeof(StackFrame).GetConstructor(new Type[] { typeof(int), typeof(bool) }));
MethodWrapper callerID = CoreClasses.ikvm.@internal.CallerID.Wrapper.GetMethodWrapper("create", "(Lcli.System.Diagnostics.StackFrame;)Likvm.internal.CallerID;", false);
callerID.Link();
callerID.EmitCall(ilgen);
if (mw.IsStatic)
2005-11-01 17:01:42 +03:00
{
mw.EmitCall(ilgen);
2005-11-01 17:01:42 +03:00
}
else
2005-11-01 17:01:42 +03:00
{
mw.EmitCallvirt(ilgen);
2005-11-01 17:01:42 +03:00
}
ilgen.Emit(OpCodes.Ret);
2005-11-01 17:01:42 +03:00
}
#endif // STATIC_COMPILER
2005-11-01 17:01:42 +03:00
private void AddMethodOverride(MethodWrapper method, MethodBuilder mb, TypeWrapper iface, string name, string sig, ref Hashtable hashtable, bool unloadableOnly)
2005-11-01 17:01:42 +03:00
{
if (hashtable != null && hashtable.ContainsKey(iface))
2005-11-01 17:01:42 +03:00
{
return;
2005-11-01 17:01:42 +03:00
}
MethodWrapper mw = iface.GetMethodWrapper(name, sig, false);
if (mw != null)
2005-11-01 17:01:42 +03:00
{
if (hashtable == null)
{
hashtable = new Hashtable();
}
hashtable.Add(iface, iface);
if (CheckRequireOverrideStub(method, mw))
{
JavaTypeImpl.GenerateUnloadableOverrideStub(wrapper, typeBuilder, mw, mb, method.ReturnTypeForDefineMethod, method.GetParametersForDefineMethod());
}
else if (!unloadableOnly)
{
typeBuilder.DefineMethodOverride(mb, (MethodInfo)mw.GetMethod());
}
2005-11-01 17:01:42 +03:00
}
foreach (TypeWrapper iface2 in iface.Interfaces)
2005-11-01 17:01:42 +03:00
{
AddMethodOverride(method, mb, iface2, name, sig, ref hashtable, unloadableOnly);
2005-11-01 17:01:42 +03:00
}
}
private static bool CheckRequireOverrideStub(MethodWrapper mw1, MethodWrapper mw2)
2005-11-01 17:01:42 +03:00
{
// TODO this is too late to generate LinkageErrors so we need to figure this out earlier
if (mw1.ReturnType != mw2.ReturnType && !(mw1.ReturnType.IsUnloadable && mw2.ReturnType.IsUnloadable))
2005-11-01 17:01:42 +03:00
{
return true;
2005-11-01 17:01:42 +03:00
}
TypeWrapper[] args1 = mw1.GetParameters();
TypeWrapper[] args2 = mw2.GetParameters();
for (int i = 0; i < args1.Length; i++)
{
if (args1[i] != args2[i] && !(args1[i].IsUnloadable && args2[i].IsUnloadable))
{
return true;
}
}
return false;
2005-11-01 17:01:42 +03:00
}
private void ImplementInterfaces(TypeWrapper[] interfaces, ArrayList interfaceList)
2005-11-01 17:01:42 +03:00
{
foreach (TypeWrapper iface in interfaces)
2005-11-01 17:01:42 +03:00
{
if (!interfaceList.Contains(iface))
{
interfaceList.Add(iface);
// NOTE we're using TypeAsBaseType for the interfaces!
Type ifaceType = iface.TypeAsBaseType;
if (!iface.IsPublic && !ifaceType.Assembly.Equals(typeBuilder.Assembly))
{
ifaceType = ifaceType.Assembly.GetType(DynamicClassLoader.GetProxyHelperName(ifaceType));
}
typeBuilder.AddInterfaceImplementation(ifaceType);
#if STATIC_COMPILER
if (!wrapper.IsInterface)
{
// look for "magic" interfaces that imply a .NET interface
if (iface.GetClassLoader() == CoreClasses.java.lang.Object.Wrapper.GetClassLoader())
{
if (iface.Name == "java.lang.Iterable"
&& !wrapper.ImplementsInterface(ClassLoaderWrapper.GetWrapperFromType(typeof(IEnumerable))))
{
TypeWrapper enumeratorType = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedNameFast("ikvm.lang.IterableEnumerator");
if (enumeratorType != null)
{
typeBuilder.AddInterfaceImplementation(typeof(IEnumerable));
// FXBUG we're using the same method name as the C# compiler here because both the .NET and Mono implementations of Xml serialization depend on this method name
MethodBuilder mb = typeBuilder.DefineMethod("System.Collections.IEnumerable.GetEnumerator", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName, typeof(IEnumerator), Type.EmptyTypes);
AttributeHelper.HideFromJava(mb);
typeBuilder.DefineMethodOverride(mb, typeof(IEnumerable).GetMethod("GetEnumerator"));
CodeEmitter ilgen = CodeEmitter.Create(mb);
ilgen.Emit(OpCodes.Ldarg_0);
MethodWrapper mw = enumeratorType.GetMethodWrapper("<init>", "(Ljava.lang.Iterable;)V", false);
mw.Link();
mw.EmitNewobj(ilgen);
ilgen.Emit(OpCodes.Ret);
}
}
else if (iface.Name == "java.io.Closeable"
&& !wrapper.ImplementsInterface(ClassLoaderWrapper.GetWrapperFromType(typeof(IDisposable))))
{
typeBuilder.AddInterfaceImplementation(typeof(IDisposable));
MethodBuilder mb = typeBuilder.DefineMethod("__<>Dispose", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.SpecialName, typeof(void), Type.EmptyTypes);
typeBuilder.DefineMethodOverride(mb, typeof(IDisposable).GetMethod("Dispose"));
CodeEmitter ilgen = CodeEmitter.Create(mb);
ilgen.Emit(OpCodes.Ldarg_0);
MethodWrapper mw = iface.GetMethodWrapper("close", "()V", false);
mw.Link();
mw.EmitCallvirt(ilgen);
ilgen.Emit(OpCodes.Ret);
}
}
// if we implement a ghost interface, add an implicit conversion to the ghost reference value type
if (iface.IsGhost && wrapper.IsPublic)
{
MethodBuilder mb = typeBuilder.DefineMethod("op_Implicit", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName, iface.TypeAsSignatureType, new Type[] { wrapper.TypeAsSignatureType });
CodeEmitter ilgen = CodeEmitter.Create(mb);
LocalBuilder local = ilgen.DeclareLocal(iface.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Stfld, iface.GhostRefField);
ilgen.Emit(OpCodes.Ldloca, local);
ilgen.Emit(OpCodes.Ldobj, iface.TypeAsSignatureType);
ilgen.Emit(OpCodes.Ret);
}
}
#endif // STATIC_COMPILER
// NOTE we're recursively "implementing" all interfaces that we inherit from the interfaces we implement.
// The C# compiler also does this and the Compact Framework requires it.
ImplementInterfaces(iface.Interfaces, interfaceList);
}
2005-11-01 17:01:42 +03:00
}
}
private void AddUnsupportedAbstractMethods()
2005-11-01 17:01:42 +03:00
{
foreach (MethodBase mb in wrapper.BaseTypeWrapper.TypeAsBaseType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
2005-11-01 17:01:42 +03:00
{
if (DotNetTypeWrapper.IsUnsupportedAbstractMethod(mb))
{
GenerateUnsupportedAbstractMethodStub(mb);
}
2005-11-01 17:01:42 +03:00
}
Hashtable h = new Hashtable();
TypeWrapper tw = wrapper;
while (tw != null)
2005-11-01 17:01:42 +03:00
{
foreach (TypeWrapper iface in tw.Interfaces)
{
foreach (MethodBase mb in iface.TypeAsBaseType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
if (!h.ContainsKey(mb))
{
h.Add(mb, mb);
if (DotNetTypeWrapper.IsUnsupportedAbstractMethod(mb))
{
GenerateUnsupportedAbstractMethodStub(mb);
}
}
}
}
tw = tw.BaseTypeWrapper;
2005-11-01 17:01:42 +03:00
}
}
private void GenerateUnsupportedAbstractMethodStub(MethodBase mb)
2005-11-01 17:01:42 +03:00
{
ParameterInfo[] parameters = mb.GetParameters();
Type[] parameterTypes = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
2005-11-01 17:01:42 +03:00
{
parameterTypes[i] = parameters[i].ParameterType;
2005-11-01 17:01:42 +03:00
}
MethodAttributes attr = MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Private;
MethodBuilder m = typeBuilder.DefineMethod("__<unsupported>" + mb.DeclaringType.FullName + "/" + mb.Name, attr, ((MethodInfo)mb).ReturnType, parameterTypes);
EmitHelper.Throw(CodeEmitter.Create(m), "java.lang.AbstractMethodError", "Method " + mb.DeclaringType.FullName + "." + mb.Name + " is unsupported by IKVM.");
typeBuilder.DefineMethodOverride(m, (MethodInfo)mb);
2005-11-01 17:01:42 +03:00
}
2005-06-01 13:49:30 +04:00
private void CompileConstructorBody(FinishContext context, CodeEmitter ilGenerator, int methodIndex, Hashtable invokespecialstubcache)
2003-02-18 12:30:34 +03:00
{
MethodWrapper[] methods = wrapper.GetMethods();
ClassFile.Method m = classFile.Methods[methodIndex];
TraceHelper.EmitMethodTrace(ilGenerator, classFile.Name + "." + m.Name + m.Signature);
2006-12-28 10:46:21 +03:00
#if STATIC_COMPILER
// do we have a native implementation in map.xml?
if (wrapper.EmitMapXmlMethodBody(ilGenerator, classFile, m))
2005-06-01 13:49:30 +04:00
{
return;
2005-06-01 13:49:30 +04:00
}
#endif
LineNumberTableAttribute.LineNumberWriter lineNumberTable = null;
bool nonLeaf = false;
Compiler.Compile(context, wrapper, methods[methodIndex], classFile, m, ilGenerator, ref nonLeaf, invokespecialstubcache, ref lineNumberTable);
if (lineNumberTable != null)
2005-06-01 13:49:30 +04:00
{
#if STATIC_COMPILER
AttributeHelper.SetLineNumberTable(methods[methodIndex].GetMethod(), lineNumberTable);
#else // STATIC_COMPILER
if (wrapper.lineNumberTables == null)
{
wrapper.lineNumberTables = new byte[methods.Length][];
}
wrapper.lineNumberTables[methodIndex] = lineNumberTable.ToArray();
#endif // STATIC_COMPILER
2005-06-01 13:49:30 +04:00
}
2002-12-18 19:00:25 +03:00
}
private static bool IsCompatibleArgList(TypeWrapper[] caller, TypeWrapper[] callee)
2005-06-01 13:49:30 +04:00
{
if (caller.Length == callee.Length)
2005-06-01 13:49:30 +04:00
{
for (int i = 0; i < caller.Length; i++)
{
if (!caller[i].IsAssignableTo(callee[i]))
{
return false;
}
}
return true;
2005-06-01 13:49:30 +04:00
}
return false;
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
private void EmitCallerIDInitialization(CodeEmitter ilGenerator)
2005-08-24 12:14:23 +04:00
{
if (callerIDField != null)
2005-08-24 12:14:23 +04:00
{
TypeWrapper tw = CoreClasses.ikvm.@internal.CallerID.Wrapper;
// we need to prohibit this optimization at runtime, because proxy classes may be injected into the boot class loader,
// but they don't actually have access to core library internals
2006-12-28 10:46:21 +03:00
#if STATIC_COMPILER
if (tw.GetClassLoader() == wrapper.GetClassLoader())
{
MethodWrapper create = tw.GetMethodWrapper("create", "(Lcli.System.RuntimeTypeHandle;)Likvm.internal.CallerID;", false);
ilGenerator.Emit(OpCodes.Ldtoken, this.typeBuilder);
create.Link();
create.EmitCall(ilGenerator);
}
else
#endif
{
typeCallerID = typeBuilder.DefineNestedType("__<CallerID>", TypeAttributes.Sealed | TypeAttributes.NestedPrivate, tw.TypeAsBaseType);
ConstructorBuilder cb = typeCallerID.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, null);
CodeEmitter ctorIlgen = CodeEmitter.Create(cb);
ctorIlgen.Emit(OpCodes.Ldarg_0);
MethodWrapper mw = tw.GetMethodWrapper("<init>", "()V", false);
mw.Link();
mw.EmitCall(ctorIlgen);
ctorIlgen.Emit(OpCodes.Ret);
ilGenerator.Emit(OpCodes.Newobj, cb);
}
ilGenerator.Emit(OpCodes.Stsfld, callerIDField);
2006-12-28 10:46:21 +03:00
}
}
private void EmitConstantValueInitialization(FieldWrapper[] fields, CodeEmitter ilGenerator)
2006-12-28 10:46:21 +03:00
{
ClassFile.Field[] flds = classFile.Fields;
for (int i = 0; i < flds.Length; i++)
2006-12-28 10:46:21 +03:00
{
ClassFile.Field f = flds[i];
if (f.IsStatic && !f.IsFinal)
{
object constant = f.ConstantValue;
if (constant != null)
{
if (constant is int)
{
ilGenerator.Emit(OpCodes.Ldc_I4, (int)constant);
}
else if (constant is long)
{
ilGenerator.Emit(OpCodes.Ldc_I8, (long)constant);
}
else if (constant is double)
{
ilGenerator.Emit(OpCodes.Ldc_R8, (double)constant);
}
else if (constant is float)
{
ilGenerator.Emit(OpCodes.Ldc_R4, (float)constant);
}
else if (constant is string)
{
ilGenerator.Emit(OpCodes.Ldstr, (string)constant);
}
else
{
throw new InvalidOperationException();
}
fields[i].EmitSet(ilGenerator);
}
}
2006-12-28 10:46:21 +03:00
}
}
2005-06-01 13:49:30 +04:00
}
protected static void GetParameterNamesFromLVT(ClassFile.Method m, string[] parameterNames)
2005-06-01 13:49:30 +04:00
{
ClassFile.Method.LocalVariableTableEntry[] localVars = m.LocalVariableTableAttribute;
if(localVars != null)
2005-05-30 19:30:13 +04:00
{
for(int i = m.IsStatic ? 0 : 1, pos = 0; i < m.ArgMap.Length; i++)
2005-05-30 19:30:13 +04:00
{
// skip double & long fillers
2005-06-01 13:49:30 +04:00
if(m.ArgMap[i] != -1)
2005-05-30 19:30:13 +04:00
{
if(parameterNames[pos] == null)
2005-05-30 19:30:13 +04:00
{
for(int j = 0; j < localVars.Length; j++)
2005-05-30 19:30:13 +04:00
{
if(localVars[j].index == i)
2005-06-01 13:49:30 +04:00
{
parameterNames[pos] = localVars[j].name;
break;
2005-06-01 13:49:30 +04:00
}
2005-05-30 19:30:13 +04:00
}
}
pos++;
2005-05-30 19:30:13 +04:00
}
}
}
2004-01-18 01:46:43 +03:00
}
protected static void GetParameterNamesFromSig(string sig, string[] parameterNames)
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
ArrayList names = new ArrayList();
for(int i = 1; sig[i] != ')'; i++)
2005-05-30 19:30:13 +04:00
{
if(sig[i] == 'L')
{
i++;
int end = sig.IndexOf(';', i);
2005-06-01 13:49:30 +04:00
names.Add(GetParameterName(sig.Substring(i, end - i)));
2005-05-30 19:30:13 +04:00
i = end;
}
2005-06-01 13:49:30 +04:00
else if(sig[i] == '[')
{
while(sig[++i] == '[');
if(sig[i] == 'L')
{
i++;
int end = sig.IndexOf(';', i);
names.Add(GetParameterName(sig.Substring(i, end - i)) + "arr");
i = end;
}
else
{
switch(sig[i])
{
case 'B':
case 'Z':
names.Add("barr");
break;
case 'C':
names.Add("charr");
break;
case 'S':
names.Add("sarr");
break;
case 'I':
names.Add("iarr");
break;
case 'J':
names.Add("larr");
break;
case 'F':
names.Add("farr");
break;
case 'D':
names.Add("darr");
break;
}
}
}
2005-05-30 19:30:13 +04:00
else
{
switch(sig[i])
{
case 'B':
case 'Z':
2005-06-01 13:49:30 +04:00
names.Add("b");
2005-05-30 19:30:13 +04:00
break;
case 'C':
2005-06-01 13:49:30 +04:00
names.Add("ch");
2005-05-30 19:30:13 +04:00
break;
case 'S':
2005-06-01 13:49:30 +04:00
names.Add("s");
2005-05-30 19:30:13 +04:00
break;
case 'I':
2005-06-01 13:49:30 +04:00
names.Add("i");
2005-05-30 19:30:13 +04:00
break;
case 'J':
2005-06-01 13:49:30 +04:00
names.Add("l");
2005-05-30 19:30:13 +04:00
break;
case 'F':
2005-06-01 13:49:30 +04:00
names.Add("f");
2005-05-30 19:30:13 +04:00
break;
case 'D':
2005-06-01 13:49:30 +04:00
names.Add("d");
2005-05-30 19:30:13 +04:00
break;
}
}
}
for(int i = 0; i < parameterNames.Length; i++)
2005-05-30 19:30:13 +04:00
{
if(parameterNames[i] == null)
2005-05-30 19:30:13 +04:00
{
parameterNames[i] = (string)names[i];
2005-06-01 13:49:30 +04:00
}
}
}
protected static ParameterBuilder[] GetParameterBuilders(MethodBase mb, int parameterCount, string[] parameterNames)
{
ParameterBuilder[] parameterBuilders = new ParameterBuilder[parameterCount];
Hashtable clashes = null;
for(int i = 0; i < parameterBuilders.Length; i++)
{
string name = null;
if(parameterNames != null)
2005-06-01 13:49:30 +04:00
{
name = parameterNames[i];
if(Array.IndexOf(parameterNames, name, i + 1) >= 0 || (clashes != null && clashes.ContainsKey(name)))
2005-06-01 13:49:30 +04:00
{
if(clashes == null)
{
clashes = new Hashtable();
}
int clash = 1;
if(clashes.ContainsKey(name))
{
clash = (int)clashes[name] + 1;
}
clashes[name] = clash;
name += clash;
2005-06-01 13:49:30 +04:00
}
2005-05-30 19:30:13 +04:00
}
MethodBuilder mBuilder = mb as MethodBuilder;
if(mBuilder != null)
2005-06-01 13:49:30 +04:00
{
parameterBuilders[i] = mBuilder.DefineParameter(i + 1, ParameterAttributes.None, name);
2005-06-01 13:49:30 +04:00
}
else
{
parameterBuilders[i] = ((ConstructorBuilder)mb).DefineParameter(i + 1, ParameterAttributes.None, name);
2005-06-01 13:49:30 +04:00
}
2005-05-30 19:30:13 +04:00
}
2005-06-01 13:49:30 +04:00
return parameterBuilders;
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
private static string GetParameterName(string type)
2004-01-18 01:46:43 +03:00
{
2005-06-01 13:49:30 +04:00
if(type == "java.lang.String")
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
return "str";
2005-05-30 19:30:13 +04:00
}
2005-06-01 13:49:30 +04:00
else if(type == "java.lang.Object")
2005-05-30 19:30:13 +04:00
{
2005-06-01 13:49:30 +04:00
return "obj";
2005-05-30 19:30:13 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
System.Text.StringBuilder sb = new System.Text.StringBuilder();
for(int i = type.LastIndexOf('.') + 1; i < type.Length; i++)
{
if(char.IsUpper(type, i))
{
sb.Append(char.ToLower(type[i]));
}
}
return sb.ToString();
2005-05-30 19:30:13 +04:00
}
}
2006-09-12 13:57:36 +04:00
#if STATIC_COMPILER
protected abstract void AddMapXmlFields(ref FieldWrapper[] fields);
protected abstract bool EmitMapXmlMethodBody(CodeEmitter ilgen, ClassFile f, ClassFile.Method m);
2006-09-12 13:57:36 +04:00
protected abstract void EmitMapXmlMetadata(TypeBuilder typeBuilder, ClassFile classFile, FieldWrapper[] fields, MethodWrapper[] methods);
protected abstract MethodBuilder DefineGhostMethod(string name, MethodAttributes attribs, MethodWrapper mw);
protected abstract void FinishGhost(TypeBuilder typeBuilder, MethodWrapper[] methods);
protected abstract void FinishGhostStep2();
protected abstract TypeBuilder DefineGhostType(string mangledTypeName, TypeAttributes typeAttribs);
#endif // STATIC_COMPILER
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
protected virtual bool IsPInvokeMethod(ClassFile.Method m)
{
2006-06-15 16:29:11 +04:00
if(m.Annotations != null)
{
foreach(object[] annot in m.Annotations)
{
if("Lcli/System/Runtime/InteropServices/DllImportAttribute$Annotation;".Equals(annot[1]))
{
return true;
}
}
}
2005-06-01 13:49:30 +04:00
return false;
}
2005-05-30 19:30:13 +04:00
2005-06-01 13:49:30 +04:00
internal override MethodBase LinkMethod(MethodWrapper mw)
{
mw.AssertLinked();
return impl.LinkMethod(mw);
}
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal override FieldInfo LinkField(FieldWrapper fw)
{
fw.AssertLinked();
return impl.LinkField(fw);
}
2005-08-24 12:14:23 +04:00
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
2005-08-24 12:14:23 +04:00
{
impl.EmitRunClassConstructor(ilgen);
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature()
{
return impl.GetGenericSignature();
}
internal override string GetGenericMethodSignature(MethodWrapper mw)
{
MethodWrapper[] methods = GetMethods();
for(int i = 0; i < methods.Length; i++)
{
if(methods[i] == mw)
{
return impl.GetGenericMethodSignature(i);
}
}
Debug.Fail("Unreachable code");
return null;
}
internal override string GetGenericFieldSignature(FieldWrapper fw)
{
FieldWrapper[] fields = GetFields();
for(int i = 0; i < fields.Length; i++)
{
if(fields[i] == fw)
{
return impl.GetGenericFieldSignature(i + GetMethods().Length);
}
}
Debug.Fail("Unreachable code");
return null;
}
internal override string[] GetEnclosingMethod()
{
return impl.GetEnclosingMethod();
}
2005-11-01 17:01:42 +03:00
2006-05-04 12:09:56 +04:00
internal override string GetSourceFileName()
{
return sourceFileName;
}
#if !STATIC_COMPILER
2006-05-05 12:16:18 +04:00
private int GetMethodBaseToken(MethodBase mb)
{
ConstructorInfo ci = mb as ConstructorInfo;
if(ci != null)
{
2006-07-26 18:16:52 +04:00
return classLoader.GetTypeWrapperFactory().ModuleBuilder.GetConstructorToken(ci).Token;
2006-05-05 12:16:18 +04:00
}
else
{
2006-07-26 18:16:52 +04:00
return classLoader.GetTypeWrapperFactory().ModuleBuilder.GetMethodToken((MethodInfo)mb).Token;
2006-05-05 12:16:18 +04:00
}
}
2006-05-04 12:09:56 +04:00
internal override int GetSourceLineNumber(MethodBase mb, int ilOffset)
{
if(lineNumberTables != null)
{
2006-05-05 12:16:18 +04:00
int token = GetMethodBaseToken(mb);
2006-05-04 12:09:56 +04:00
MethodWrapper[] methods = GetMethods();
for(int i = 0; i < methods.Length; i++)
{
2006-05-05 12:16:18 +04:00
if(GetMethodBaseToken(methods[i].GetMethod()) == token)
2006-05-04 12:09:56 +04:00
{
if(lineNumberTables[i] != null)
{
return new LineNumberTableAttribute(lineNumberTables[i]).GetLineNumber(ilOffset);
}
break;
}
}
}
return -1;
}
2005-11-01 17:01:42 +03:00
internal override object[] GetDeclaredAnnotations()
{
object[] annotations = impl.GetDeclaredAnnotations();
2006-04-19 19:49:54 +04:00
if(annotations != null)
{
object[] objs = new object[annotations.Length];
for(int i = 0; i < annotations.Length; i++)
{
objs[i] = JVM.NewAnnotation(GetClassLoader().GetJavaClassLoader(), annotations[i]);
2006-04-19 19:49:54 +04:00
}
return objs;
}
return null;
}
internal override object[] GetMethodAnnotations(MethodWrapper mw)
{
MethodWrapper[] methods = GetMethods();
for(int i = 0; i < methods.Length; i++)
{
if(methods[i] == mw)
{
object[] annotations = impl.GetMethodAnnotations(i);
if(annotations != null)
{
object[] objs = new object[annotations.Length];
for(int j = 0; j < annotations.Length; j++)
{
objs[j] = JVM.NewAnnotation(GetClassLoader().GetJavaClassLoader(), annotations[j]);
2006-04-19 19:49:54 +04:00
}
return objs;
}
return null;
}
}
Debug.Fail("Unreachable code");
return null;
}
internal override object[][] GetParameterAnnotations(MethodWrapper mw)
{
MethodWrapper[] methods = GetMethods();
for(int i = 0; i < methods.Length; i++)
{
if(methods[i] == mw)
{
object[][] annotations = impl.GetParameterAnnotations(i);
if(annotations != null)
{
object[][] objs = new object[annotations.Length][];
for(int j = 0; j < annotations.Length; j++)
{
objs[j] = new object[annotations[j].Length];
for(int k = 0; k < annotations[j].Length; k++)
{
objs[j][k] = JVM.NewAnnotation(GetClassLoader().GetJavaClassLoader(), annotations[j][k]);
2006-04-19 19:49:54 +04:00
}
}
return objs;
}
return null;
}
}
Debug.Fail("Unreachable code");
return null;
}
internal override object[] GetFieldAnnotations(FieldWrapper fw)
{
FieldWrapper[] fields = GetFields();
for(int i = 0; i < fields.Length; i++)
2005-11-01 17:01:42 +03:00
{
2006-04-19 19:49:54 +04:00
if(fields[i] == fw)
{
object[] annotations = impl.GetFieldAnnotations(i);
if(annotations != null)
{
object[] objs = new object[annotations.Length];
for(int j = 0; j < annotations.Length; j++)
{
objs[j] = JVM.NewAnnotation(GetClassLoader().GetJavaClassLoader(), annotations[j]);
2006-04-19 19:49:54 +04:00
}
return objs;
}
return null;
}
2005-11-01 17:01:42 +03:00
}
2006-04-19 19:49:54 +04:00
Debug.Fail("Unreachable code");
return null;
2005-11-01 17:01:42 +03:00
}
internal override object GetAnnotationDefault(MethodWrapper mw)
{
MethodWrapper[] methods = GetMethods();
for(int i = 0; i < methods.Length; i++)
{
if(methods[i] == mw)
{
2006-04-19 19:49:54 +04:00
object defVal = impl.GetMethodDefaultValue(i);
if(defVal != null)
{
return JVM.NewAnnotationElementValue(mw.DeclaringType.GetClassLoader().GetJavaClassLoader(), mw.ReturnType.ClassObject, defVal);
2006-04-19 19:49:54 +04:00
}
return null;
2005-11-01 17:01:42 +03:00
}
}
Debug.Fail("Unreachable code");
return null;
}
2006-04-10 13:09:09 +04:00
#endif
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
#endif // !COMPACT_FRAMEWORK
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
class CompiledTypeWrapper : TypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly Type type;
private TypeWrapper[] interfaces;
private TypeWrapper[] innerclasses;
2005-08-24 12:14:23 +04:00
private MethodInfo clinitMethod;
private Modifiers reflectiveModifiers;
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
internal static CompiledTypeWrapper newInstance(string name, Type type)
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO since ghost and remapped types can only exist in the core library assembly, we probably
// should be able to remove the Type.IsDefined() tests in most cases
2005-12-07 12:06:32 +03:00
if(type.IsValueType && AttributeHelper.IsGhostInterface(type))
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
return new CompiledGhostTypeWrapper(name, type);
}
2005-12-07 12:06:32 +03:00
else if(AttributeHelper.IsRemappedType(type))
2005-06-01 13:49:30 +04:00
{
return new CompiledRemappedTypeWrapper(name, type);
}
else
{
return new CompiledTypeWrapper(name, type);
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
private sealed class CompiledRemappedTypeWrapper : CompiledTypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private readonly Type remappedType;
internal CompiledRemappedTypeWrapper(string name, Type type)
: base(name, type)
2005-03-23 12:33:18 +03:00
{
2005-12-07 12:06:32 +03:00
RemappedTypeAttribute attr = AttributeHelper.GetRemappedType(type);
if(attr == null)
2005-06-01 13:49:30 +04:00
{
throw new InvalidOperationException();
}
2005-12-07 12:06:32 +03:00
remappedType = attr.Type;
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return remappedType;
}
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
internal override bool IsRemapped
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
return true;
}
}
protected override void LazyPublishMembers()
{
ArrayList methods = new ArrayList();
ArrayList fields = new ArrayList();
MemberInfo[] members = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
2005-06-01 13:49:30 +04:00
foreach(MemberInfo m in members)
{
if(!AttributeHelper.IsHideFromJava(m))
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase method = m as MethodBase;
if(method != null &&
(remappedType.IsSealed || !m.Name.StartsWith("instancehelper_")) &&
(!remappedType.IsSealed || method.IsStatic))
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
methods.Add(CreateRemappedMethodWrapper(method));
}
else
{
FieldInfo field = m as FieldInfo;
if(field != null)
{
fields.Add(CreateFieldWrapper(field));
}
2005-03-23 12:33:18 +03:00
}
}
}
2005-06-01 13:49:30 +04:00
// if we're a remapped interface, we need to get the methods from the real interface
if(remappedType.IsInterface)
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
Type nestedHelper = type.GetNestedType("__Helper", BindingFlags.Public | BindingFlags.Static);
2005-12-07 12:06:32 +03:00
foreach(RemappedInterfaceMethodAttribute m in AttributeHelper.GetRemappedInterfaceMethods(type))
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodInfo method = remappedType.GetMethod(m.MappedTo);
MethodInfo mbHelper = method;
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper.GetModifiers(method, false);
2005-06-01 13:49:30 +04:00
string name;
string sig;
TypeWrapper retType;
TypeWrapper[] paramTypes;
MemberFlags flags = MemberFlags.None;
GetNameSigFromMethodBase(method, out name, out sig, out retType, out paramTypes, ref flags);
2005-06-01 13:49:30 +04:00
if(nestedHelper != null)
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
mbHelper = nestedHelper.GetMethod(m.Name);
if(mbHelper == null)
{
mbHelper = method;
}
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
methods.Add(new CompiledRemappedMethodWrapper(this, m.Name, sig, method, retType, paramTypes, modifiers, false, mbHelper, null));
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
SetMethods((MethodWrapper[])methods.ToArray(typeof(MethodWrapper)));
SetFields((FieldWrapper[])fields.ToArray(typeof(FieldWrapper)));
2005-03-23 12:33:18 +03:00
}
2005-06-01 13:49:30 +04:00
private MethodWrapper CreateRemappedMethodWrapper(MethodBase mb)
2005-03-23 12:33:18 +03:00
{
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper.GetModifiers(mb, false);
2005-06-01 13:49:30 +04:00
string name;
string sig;
TypeWrapper retType;
TypeWrapper[] paramTypes;
MemberFlags flags = MemberFlags.None;
GetNameSigFromMethodBase(mb, out name, out sig, out retType, out paramTypes, ref flags);
2005-06-01 13:49:30 +04:00
MethodInfo mbHelper = mb as MethodInfo;
2006-04-05 12:18:58 +04:00
bool hideFromReflection = mbHelper != null && AttributeHelper.IsHideFromReflection(mbHelper);
2005-06-01 13:49:30 +04:00
MethodInfo mbNonvirtualHelper = null;
if(!mb.IsStatic && !mb.IsConstructor)
{
ParameterInfo[] parameters = mb.GetParameters();
Type[] argTypes = new Type[parameters.Length + 1];
argTypes[0] = remappedType;
for(int i = 0; i < parameters.Length; i++)
{
argTypes[i + 1] = parameters[i].ParameterType;
}
MethodInfo helper = type.GetMethod("instancehelper_" + mb.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static, null, argTypes, null);
if(helper != null)
{
mbHelper = helper;
}
mbNonvirtualHelper = type.GetMethod("nonvirtualhelper/" + mb.Name, BindingFlags.NonPublic | BindingFlags.Static, null, argTypes, null);
2005-03-23 12:33:18 +03:00
}
2006-04-05 12:18:58 +04:00
return new CompiledRemappedMethodWrapper(this, name, sig, mb, retType, paramTypes, modifiers, hideFromReflection, mbHelper, mbNonvirtualHelper);
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
private sealed class CompiledGhostTypeWrapper : CompiledTypeWrapper
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
private FieldInfo ghostRefField;
private Type typeAsBaseType;
2005-03-23 12:33:18 +03:00
2005-06-01 13:49:30 +04:00
internal CompiledGhostTypeWrapper(string name, Type type)
: base(name, type)
{
}
internal override Type TypeAsBaseType
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
if(typeAsBaseType == null)
{
typeAsBaseType = type.GetNestedType("__Interface");
}
return typeAsBaseType;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override FieldInfo GhostRefField
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
if(ghostRefField == null)
{
ghostRefField = type.GetField("__<ref>");
}
return ghostRefField;
2005-03-23 12:33:18 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override bool IsGhost
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return true;
}
2005-03-23 12:33:18 +03:00
}
}
2004-01-11 16:14:42 +03:00
2005-06-01 13:49:30 +04:00
internal static string GetName(Type type)
2002-12-18 19:00:25 +03:00
{
Debug.Assert(!type.IsGenericType);
2005-12-07 12:06:32 +03:00
Debug.Assert(AttributeHelper.IsJavaModule(type.Module));
2002-12-18 19:00:25 +03:00
2005-06-01 13:49:30 +04:00
// look for our custom attribute, that contains the real name of the type (for inner classes)
2005-12-07 12:06:32 +03:00
InnerClassAttribute attr = AttributeHelper.GetInnerClass(type);
if(attr != null)
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
string name = attr.InnerClassName;
2005-07-07 15:24:08 +04:00
if(name != null)
{
return name;
}
2006-05-15 13:08:01 +04:00
if(type.DeclaringType != null)
{
return GetName(type.DeclaringType) + "$" + type.Name;
}
2005-06-01 13:49:30 +04:00
}
return type.FullName;
2003-08-13 19:00:41 +04:00
}
2005-06-01 13:49:30 +04:00
// TODO consider resolving the baseType lazily
private static TypeWrapper GetBaseTypeWrapper(Type type)
2003-08-13 19:00:41 +04:00
{
2005-12-07 12:06:32 +03:00
if(type.IsInterface || AttributeHelper.IsGhostInterface(type))
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
return null;
}
else if(type.BaseType == null)
{
// System.Object must appear to be derived from java.lang.Object
return CoreClasses.java.lang.Object.Wrapper;
}
else
{
2005-12-07 12:06:32 +03:00
RemappedTypeAttribute attr = AttributeHelper.GetRemappedType(type);
if(attr != null)
2004-03-08 18:18:47 +03:00
{
2005-12-07 12:06:32 +03:00
if(attr.Type == typeof(object))
2005-06-01 13:49:30 +04:00
{
return null;
}
else
{
return CoreClasses.java.lang.Object.Wrapper;
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper.GetWrapperFromType(type.BaseType);
2004-03-08 18:18:47 +03:00
}
2003-08-13 19:00:41 +04:00
}
2002-12-18 19:00:25 +03:00
2006-04-05 12:18:58 +04:00
private CompiledTypeWrapper(ExModifiers exmod, string name, TypeWrapper baseTypeWrapper)
: base(exmod.Modifiers, name, baseTypeWrapper)
{
this.IsInternal = exmod.IsInternal;
}
2005-06-01 13:49:30 +04:00
private CompiledTypeWrapper(string name, Type type)
2006-04-05 12:18:58 +04:00
: this(GetModifiers(type), name, GetBaseTypeWrapper(type))
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(!(type is TypeBuilder));
2007-01-16 13:14:47 +03:00
Debug.Assert(!type.Name.EndsWith("[]"));
2005-06-01 13:49:30 +04:00
this.type = type;
2003-05-30 16:08:59 +04:00
}
2005-06-01 13:49:30 +04:00
2006-03-23 14:57:41 +03:00
internal override ClassLoaderWrapper GetClassLoader()
{
2006-05-15 13:08:01 +04:00
return ClassLoaderWrapper.GetAssemblyClassLoader(type.Assembly);
2006-03-23 14:57:41 +03:00
}
2006-04-05 12:18:58 +04:00
private static ExModifiers GetModifiers(Type type)
2002-12-18 19:00:25 +03:00
{
2005-12-07 12:06:32 +03:00
ModifiersAttribute attr = AttributeHelper.GetModifiersAttribute(type);
if(attr != null)
2005-06-01 13:49:30 +04:00
{
2006-04-05 12:18:58 +04:00
return new ExModifiers(attr.Modifiers, attr.IsInternal);
2005-06-01 13:49:30 +04:00
}
// only returns public, protected, private, final, static, abstract and interface (as per
// the documentation of Class.getModifiers())
Modifiers modifiers = 0;
if(type.IsPublic)
{
modifiers |= Modifiers.Public;
}
// TODO do we really need to look for nested attributes? I think all inner classes will have the ModifiersAttribute.
else if(type.IsNestedPublic)
{
modifiers |= Modifiers.Public | Modifiers.Static;
}
else if(type.IsNestedPrivate)
{
modifiers |= Modifiers.Private | Modifiers.Static;
}
else if(type.IsNestedFamily || type.IsNestedFamORAssem)
{
modifiers |= Modifiers.Protected | Modifiers.Static;
}
else if(type.IsNestedAssembly || type.IsNestedFamANDAssem)
{
modifiers |= Modifiers.Static;
}
if(type.IsSealed)
{
modifiers |= Modifiers.Final;
}
if(type.IsAbstract)
{
modifiers |= Modifiers.Abstract;
}
if(type.IsInterface)
{
modifiers |= Modifiers.Interface;
}
2006-04-05 12:18:58 +04:00
return new ExModifiers(modifiers, false);
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
internal override bool HasStaticInitializer
2004-09-15 17:35:44 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2005-08-24 12:14:23 +04:00
// trigger LazyPublishMembers
GetMethods();
return clinitMethod != null;
2005-06-01 13:49:30 +04:00
}
2004-09-15 17:35:44 +04:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] Interfaces
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
get
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
if(interfaces == null)
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
// NOTE instead of getting the interfaces list from Type, we use a custom
// attribute to list the implemented interfaces, because Java reflection only
// reports the interfaces *directly* implemented by the type, not the inherited
// interfaces. This is significant for serialVersionUID calculation (for example).
2005-12-07 12:06:32 +03:00
ImplementsAttribute attr = AttributeHelper.GetImplements(type);
if(attr != null)
2005-06-01 13:49:30 +04:00
{
2005-12-07 12:06:32 +03:00
string[] interfaceNames = attr.Interfaces;
2005-06-01 13:49:30 +04:00
TypeWrapper[] interfaceWrappers = new TypeWrapper[interfaceNames.Length];
for(int i = 0; i < interfaceWrappers.Length; i++)
{
interfaceWrappers[i] = GetClassLoader().LoadClassByDottedName(interfaceNames[i]);
}
this.interfaces = interfaceWrappers;
}
else
2004-05-14 13:31:54 +04:00
{
2005-06-01 13:49:30 +04:00
interfaces = TypeWrapper.EmptyArray;
2004-05-14 13:31:54 +04:00
}
2002-12-18 19:00:25 +03:00
}
2005-06-01 13:49:30 +04:00
return interfaces;
2002-12-18 19:00:25 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] InnerClasses
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO why are we caching this?
if(innerclasses == null)
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
ArrayList wrappers = new ArrayList();
for(int i = 0; i < nestedTypes.Length; i++)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
if(!AttributeHelper.IsHideFromJava(nestedTypes[i]))
{
wrappers.Add(ClassLoaderWrapper.GetWrapperFromType(nestedTypes[i]));
}
2003-10-17 12:08:31 +04:00
}
foreach(string s in AttributeHelper.GetNonNestedInnerClasses(type))
{
wrappers.Add(GetClassLoader().LoadClassByDottedName(s));
}
2005-06-01 13:49:30 +04:00
innerclasses = (TypeWrapper[])wrappers.ToArray(typeof(TypeWrapper));
2003-02-20 17:18:38 +03:00
}
2005-06-01 13:49:30 +04:00
return innerclasses;
2003-02-18 12:30:34 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-18 12:30:34 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-20 17:18:38 +03:00
{
2005-06-01 13:49:30 +04:00
Type declaringType = type.DeclaringType;
if(declaringType != null)
{
return ClassLoaderWrapper.GetWrapperFromType(declaringType);
}
string decl = AttributeHelper.GetNonNestedOuterClasses(type);
if(decl != null)
{
return GetClassLoader().LoadClassByDottedName(decl);
}
2005-06-01 13:49:30 +04:00
return null;
2003-02-20 17:18:38 +03:00
}
2003-02-18 12:30:34 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-05-30 16:08:59 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-05-30 16:08:59 +04:00
{
if (reflectiveModifiers == 0)
2005-06-01 13:49:30 +04:00
{
InnerClassAttribute attr = AttributeHelper.GetInnerClass(type);
if (attr != null)
{
reflectiveModifiers = attr.Modifiers;
}
else
{
reflectiveModifiers = Modifiers;
}
2005-06-01 13:49:30 +04:00
}
return reflectiveModifiers;
2004-08-17 13:05:21 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsBaseType
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return type;
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private void SigTypePatchUp(string sigtype, ref TypeWrapper type)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if(sigtype != type.SigName)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
// if type is an array, we know that it is a ghost array, because arrays of unloadable are compiled
// as object (not as arrays of object)
if(type.IsArray)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
type = GetClassLoader().FieldTypeWrapperFromSig(sigtype);
}
2006-10-04 13:03:18 +04:00
else if(type.IsPrimitive)
{
type = DotNetTypeWrapper.GetWrapperFromDotNetType(type.TypeAsTBD);
if(sigtype != type.SigName)
{
throw new InvalidOperationException();
}
}
else if(type.IsNonPrimitiveValueType)
{
// this can't happen and even if it does happen we cannot return
// UnloadableTypeWrapper because that would result in incorrect code
// being generated
throw new InvalidOperationException();
}
2005-06-01 13:49:30 +04:00
else
{
if(sigtype[0] == 'L')
{
sigtype = sigtype.Substring(1, sigtype.Length - 2);
}
2006-10-04 13:03:18 +04:00
try
{
TypeWrapper tw = GetClassLoader().LoadClassByDottedNameFast(sigtype);
if(tw != null && tw.IsRemapped)
{
type = tw;
return;
}
}
catch(RetargetableJavaException)
{
}
2005-06-01 13:49:30 +04:00
type = new UnloadableTypeWrapper(sigtype);
2004-08-17 13:05:21 +04:00
}
2003-05-30 16:08:59 +04:00
}
}
2005-06-01 13:49:30 +04:00
private static void ParseSig(string sig, out string[] sigparam, out string sigret)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
ArrayList list = new ArrayList();
int pos = 1;
for(;;)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
switch(sig[pos])
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
case 'L':
2004-08-17 13:05:21 +04:00
{
int end = sig.IndexOf(';', pos) + 1;
list.Add(sig.Substring(pos, end - pos));
pos = end;
2005-06-01 13:49:30 +04:00
break;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
case '[':
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
int skip = 1;
while(sig[pos + skip] == '[') skip++;
if(sig[pos + skip] == 'L')
{
int end = sig.IndexOf(';', pos) + 1;
list.Add(sig.Substring(pos, end - pos));
pos = end;
}
else
{
skip++;
list.Add(sig.Substring(pos, skip));
pos += skip;
}
break;
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
case ')':
sigparam = (string[])list.ToArray(typeof(string));
sigret = sig.Substring(pos + 1);
return;
default:
list.Add(sig.Substring(pos, 1));
pos++;
break;
2003-10-17 12:08:31 +04:00
}
}
}
private void GetNameSigFromMethodBase(MethodBase method, out string name, out string sig, out TypeWrapper retType, out TypeWrapper[] paramTypes, ref MemberFlags flags)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
retType = method is ConstructorInfo ? PrimitiveTypeWrapper.VOID : ClassLoaderWrapper.GetWrapperFromType(((MethodInfo)method).ReturnType);
ParameterInfo[] parameters = method.GetParameters();
int len = parameters.Length;
if(len > 0
&& parameters[len - 1].ParameterType == CoreClasses.ikvm.@internal.CallerID.Wrapper.TypeAsSignatureType
&& !method.DeclaringType.IsInterface
&& ClassLoaderWrapper.IsCoreAssemblyType(method.DeclaringType))
{
len--;
flags |= MemberFlags.CallerID;
}
paramTypes = new TypeWrapper[len];
for(int i = 0; i < len; i++)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
paramTypes[i] = ClassLoaderWrapper.GetWrapperFromType(parameters[i].ParameterType);
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
NameSigAttribute attr = AttributeHelper.GetNameSig(method);
if(attr != null)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
name = attr.Name;
sig = attr.Sig;
string[] sigparams;
string sigret;
ParseSig(sig, out sigparams, out sigret);
// HACK newhelper methods have a return type, but it should be void
if(name == "<init>")
{
retType = PrimitiveTypeWrapper.VOID;
}
SigTypePatchUp(sigret, ref retType);
// if we have a remapped method, the paramTypes array contains an additional entry for "this" so we have
// to remove that
if(paramTypes.Length == sigparams.Length + 1)
{
TypeWrapper[] temp = paramTypes;
paramTypes = new TypeWrapper[sigparams.Length];
Array.Copy(temp, 1, paramTypes, 0, paramTypes.Length);
}
Debug.Assert(sigparams.Length == paramTypes.Length);
for(int i = 0; i < sigparams.Length; i++)
{
SigTypePatchUp(sigparams[i], ref paramTypes[i]);
}
2004-08-17 13:05:21 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
if(method is ConstructorInfo)
{
name = method.IsStatic ? "<clinit>" : "<init>";
}
else
{
name = method.Name;
}
System.Text.StringBuilder sb = new System.Text.StringBuilder("(");
foreach(TypeWrapper tw in paramTypes)
{
sb.Append(tw.SigName);
}
sb.Append(")");
sb.Append(retType.SigName);
sig = sb.ToString();
2004-08-17 13:05:21 +04:00
}
2003-10-17 12:08:31 +04:00
}
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers()
2004-03-08 18:18:47 +03:00
{
2005-08-24 12:14:23 +04:00
clinitMethod = type.GetMethod("__<clinit>", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
2005-06-01 13:49:30 +04:00
ArrayList methods = new ArrayList();
ArrayList fields = new ArrayList();
MemberInfo[] members = type.GetMembers(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
2005-06-01 13:49:30 +04:00
foreach(MemberInfo m in members)
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
if(!AttributeHelper.IsHideFromJava(m))
2005-03-23 12:33:18 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase method = m as MethodBase;
if(method != null)
2004-07-10 11:19:42 +04:00
{
2005-08-24 12:14:23 +04:00
if(method.IsSpecialName &&
(method.Name == "op_Implicit" || method.Name.StartsWith("__<")))
2005-07-07 18:03:21 +04:00
{
// skip
}
else
{
string name;
string sig;
TypeWrapper retType;
TypeWrapper[] paramTypes;
MethodInfo mi = method as MethodInfo;
2005-08-14 19:49:50 +04:00
bool hideFromReflection = mi != null ? AttributeHelper.IsHideFromReflection(mi) : false;
MemberFlags flags = hideFromReflection ? MemberFlags.HideFromReflection : MemberFlags.None;
GetNameSigFromMethodBase(method, out name, out sig, out retType, out paramTypes, ref flags);
2006-04-05 12:18:58 +04:00
ExModifiers mods = AttributeHelper.GetModifiers(method, false);
if(mods.IsInternal)
{
flags |= MemberFlags.InternalAccess;
}
methods.Add(MethodWrapper.Create(this, name, sig, method, retType, paramTypes, mods.Modifiers, flags));
2005-07-07 18:03:21 +04:00
}
2005-06-01 13:49:30 +04:00
}
else
{
FieldInfo field = m as FieldInfo;
if(field != null)
{
2005-07-07 18:03:21 +04:00
if(field.IsSpecialName && field.Name.StartsWith("__<"))
{
// skip
}
else
{
fields.Add(CreateFieldWrapper(field));
}
2005-06-01 13:49:30 +04:00
}
2005-08-14 19:49:50 +04:00
else
{
2006-09-26 08:53:16 +04:00
// NOTE explictly defined properties (in map.xml) are decorated with HideFromJava,
// so we don't need to worry about them here
2005-08-14 19:49:50 +04:00
PropertyInfo property = m as PropertyInfo;
if(property != null)
{
// Only AccessStub properties (marked by HideFromReflectionAttribute)
// are considered here
if(AttributeHelper.IsHideFromReflection(property))
{
fields.Add(new CompiledAccessStubFieldWrapper(this, property));
}
2006-08-15 12:50:43 +04:00
else
{
// If the property has a ModifiersAttribute, we know that it is an explicit property
// (defined in Java source by an @ikvm.lang.Property annotation)
ModifiersAttribute mods = AttributeHelper.GetModifiersAttribute(property);
if(mods != null)
{
fields.Add(new CompiledPropertyFieldWrapper(this, property, new ExModifiers(mods.Modifiers, mods.IsInternal)));
}
else
{
fields.Add(CreateFieldWrapper(property));
}
2006-08-15 12:50:43 +04:00
}
2005-08-14 19:49:50 +04:00
}
}
2004-07-10 11:19:42 +04:00
}
2004-03-08 18:18:47 +03:00
}
}
2005-06-01 13:49:30 +04:00
SetMethods((MethodWrapper[])methods.ToArray(typeof(MethodWrapper)));
SetFields((FieldWrapper[])fields.ToArray(typeof(FieldWrapper)));
2004-03-08 18:18:47 +03:00
}
2004-06-14 14:36:38 +04:00
2005-06-01 13:49:30 +04:00
private class CompiledRemappedMethodWrapper : SmartMethodWrapper
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
private MethodInfo mbHelper;
#if !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
private MethodInfo mbNonvirtualHelper;
#endif
2004-06-14 14:36:38 +04:00
2006-04-05 12:18:58 +04:00
internal CompiledRemappedMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, ExModifiers modifiers, bool hideFromReflection, MethodInfo mbHelper, MethodInfo mbNonvirtualHelper)
: base(declaringType, name, sig, method, returnType, parameterTypes, modifiers.Modifiers,
(modifiers.IsInternal ? MemberFlags.InternalAccess : MemberFlags.None) | (hideFromReflection ? MemberFlags.HideFromReflection : MemberFlags.None))
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
this.mbHelper = mbHelper;
#if !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
this.mbNonvirtualHelper = mbNonvirtualHelper;
#endif
2004-08-17 13:05:21 +04:00
}
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
protected override void CallImpl(CodeEmitter ilgen)
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod();
MethodInfo mi = mb as MethodInfo;
if(mi != null)
{
ilgen.Emit(OpCodes.Call, mi);
}
else
{
ilgen.Emit(OpCodes.Call, (ConstructorInfo)mb);
}
2004-06-14 14:36:38 +04:00
}
2005-06-01 13:49:30 +04:00
protected override void CallvirtImpl(CodeEmitter ilgen)
2004-06-14 14:36:38 +04:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(!mbHelper.IsStatic || mbHelper.Name.StartsWith("instancehelper_") || mbHelper.DeclaringType.Name == "__Helper");
2006-11-20 12:21:38 +03:00
if(mbHelper.IsPublic)
{
ilgen.Emit(mbHelper.IsStatic ? OpCodes.Call : OpCodes.Callvirt, mbHelper);
}
else
{
// HACK the helper is not public, this means that we're dealing with finalize or clone
ilgen.Emit(OpCodes.Callvirt, (MethodInfo)GetMethod());
}
2004-06-14 14:36:38 +04:00
}
2004-08-17 13:05:21 +04:00
protected override void NewobjImpl(CodeEmitter ilgen)
2002-12-18 19:00:25 +03:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod();
MethodInfo mi = mb as MethodInfo;
if(mi != null)
2003-09-10 18:58:19 +04:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(mi.Name == "newhelper");
ilgen.Emit(OpCodes.Call, mi);
2003-07-02 18:50:35 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-07-02 18:50:35 +04:00
{
2005-06-01 13:49:30 +04:00
ilgen.Emit(OpCodes.Newobj, (ConstructorInfo)mb);
2003-07-02 18:50:35 +04:00
}
2005-06-01 13:49:30 +04:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
#if !STATIC_COMPILER && !FIRST_PASS
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2005-06-01 13:49:30 +04:00
{
MethodBase mb;
if(nonVirtual)
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
if(DeclaringType.TypeAsBaseType.IsInstanceOfType(obj))
{
mb = GetMethod();
}
else if(mbNonvirtualHelper != null)
{
mb = mbNonvirtualHelper;
}
else if(mbHelper != null)
{
mb = mbHelper;
}
else
{
// we can end up here if someone calls a constructor with nonVirtual set (which is pointless, but legal)
mb = GetMethod();
}
2004-03-08 18:18:47 +03:00
}
else
{
2005-06-01 13:49:30 +04:00
mb = mbHelper != null ? mbHelper : GetMethod();
2004-03-08 18:18:47 +03:00
}
return InvokeImpl(mb, obj, args, nonVirtual, callerID);
2004-03-08 18:18:47 +03:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-10-01 15:16:11 +04:00
internal string GetGenericSignature()
{
2006-07-21 14:18:13 +04:00
SignatureAttribute attr = AttributeHelper.GetSignature(mbHelper != null ? mbHelper : GetMethod());
if(attr != null)
2005-10-01 15:16:11 +04:00
{
2006-07-21 14:18:13 +04:00
return attr.Signature;
2005-10-01 15:16:11 +04:00
}
return null;
}
2004-10-04 23:30:53 +04:00
}
2004-01-28 14:28:16 +03:00
2006-08-15 12:50:43 +04:00
private FieldWrapper CreateFieldWrapper(PropertyInfo prop)
{
MethodInfo getter = prop.GetGetMethod(true);
ExModifiers modifiers = AttributeHelper.GetModifiers(getter, false);
2006-08-17 12:14:47 +04:00
// for static methods AttributeHelper.GetModifiers won't set the Final flag
modifiers = new ExModifiers(modifiers.Modifiers | Modifiers.Final, modifiers.IsInternal);
2006-08-15 12:50:43 +04:00
string name = prop.Name;
TypeWrapper type = ClassLoaderWrapper.GetWrapperFromType(prop.PropertyType);
NameSigAttribute attr = AttributeHelper.GetNameSig(getter);
if(attr != null)
{
name = attr.Name;
SigTypePatchUp(attr.Sig, ref type);
}
return new GetterFieldWrapper(this, type, null, name, type.SigName, modifiers, getter, prop);
}
2005-06-01 13:49:30 +04:00
private FieldWrapper CreateFieldWrapper(FieldInfo field)
2002-12-18 19:00:25 +03:00
{
2006-04-05 12:18:58 +04:00
ExModifiers modifiers = AttributeHelper.GetModifiers(field, false);
2005-06-01 13:49:30 +04:00
string name = field.Name;
TypeWrapper type = ClassLoaderWrapper.GetWrapperFromType(field.FieldType);
2005-12-07 12:06:32 +03:00
NameSigAttribute attr = AttributeHelper.GetNameSig(field);
if(attr != null)
2005-06-01 13:49:30 +04:00
{
name = attr.Name;
SigTypePatchUp(attr.Sig, ref type);
}
2002-12-18 19:00:25 +03:00
2006-08-15 12:50:43 +04:00
if(field.IsLiteral)
2005-06-01 13:49:30 +04:00
{
2006-10-10 20:24:48 +04:00
MemberFlags flags = MemberFlags.None;
2005-08-14 19:49:50 +04:00
if(AttributeHelper.IsHideFromReflection(field))
{
flags |= MemberFlags.HideFromReflection;
}
2006-04-05 12:18:58 +04:00
if(modifiers.IsInternal)
{
flags |= MemberFlags.InternalAccess;
}
return new ConstantFieldWrapper(this, type, name, type.SigName, modifiers.Modifiers, field, null, flags);
2005-06-01 13:49:30 +04:00
}
else
{
return FieldWrapper.Create(this, type, field, name, type.SigName, modifiers);
}
2004-03-08 18:18:47 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2004-03-08 18:18:47 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return type;
}
2002-12-18 19:00:25 +03:00
}
2004-10-04 23:30:53 +04:00
2005-06-01 13:49:30 +04:00
internal override bool IsMapUnsafeException
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
2004-07-10 11:19:42 +04:00
{
2005-12-07 12:06:32 +03:00
return AttributeHelper.IsExceptionIsUnsafeForMapping(type);
2004-07-10 11:19:42 +04:00
}
2003-02-22 15:28:12 +03:00
}
2003-10-22 20:34:22 +04:00
2005-08-05 12:40:54 +04:00
internal override void Finish()
2003-10-22 20:34:22 +04:00
{
2006-03-01 15:26:25 +03:00
if(BaseTypeWrapper != null)
{
BaseTypeWrapper.Finish();
}
foreach(TypeWrapper tw in this.Interfaces)
{
tw.Finish();
}
2003-10-22 20:34:22 +04:00
}
2005-08-24 12:14:23 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
2005-08-24 12:14:23 +04:00
{
// trigger LazyPublishMembers
GetMethods();
if(clinitMethod != null)
{
ilgen.Emit(OpCodes.Call, clinitMethod);
}
}
2005-12-07 12:06:32 +03:00
#endif
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature()
{
2006-07-21 14:18:13 +04:00
SignatureAttribute attr = AttributeHelper.GetSignature(type);
if(attr != null)
2005-10-01 15:16:11 +04:00
{
2006-07-21 14:18:13 +04:00
return attr.Signature;
2005-10-01 15:16:11 +04:00
}
return null;
}
internal override string GetGenericMethodSignature(MethodWrapper mw)
{
if(mw is CompiledRemappedMethodWrapper)
{
return ((CompiledRemappedMethodWrapper)mw).GetGenericSignature();
}
MethodBase mb = mw.GetMethod();
if(mb != null)
{
2006-07-21 14:18:13 +04:00
SignatureAttribute attr = AttributeHelper.GetSignature(mb);
if(attr != null)
2005-10-01 15:16:11 +04:00
{
2006-07-21 14:18:13 +04:00
return attr.Signature;
2005-10-01 15:16:11 +04:00
}
}
return null;
}
internal override string GetGenericFieldSignature(FieldWrapper fw)
{
FieldInfo fi = fw.GetField();
if(fi != null)
{
2006-07-21 14:18:13 +04:00
SignatureAttribute attr = AttributeHelper.GetSignature(fi);
if(attr != null)
2005-10-01 15:16:11 +04:00
{
2006-07-21 14:18:13 +04:00
return attr.Signature;
2005-10-01 15:16:11 +04:00
}
}
2006-10-04 13:03:18 +04:00
else
{
GetterFieldWrapper getter = fw as GetterFieldWrapper;
if(getter != null)
{
SignatureAttribute attr = AttributeHelper.GetSignature(getter.GetGetter());
if(attr != null)
{
return attr.Signature;
}
}
}
2005-10-01 15:16:11 +04:00
return null;
}
internal override string[] GetEnclosingMethod()
{
object[] attr = type.GetCustomAttributes(typeof(EnclosingMethodAttribute), false);
if(attr.Length == 1)
{
EnclosingMethodAttribute enc = (EnclosingMethodAttribute)attr[0];
return new string[] { enc.ClassName, enc.MethodName, enc.MethodSignature };
}
return null;
}
2005-11-01 17:01:42 +03:00
internal override object[] GetDeclaredAnnotations()
{
if(type.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
2005-11-01 17:01:42 +03:00
return type.GetCustomAttributes(false);
}
2006-04-20 11:30:59 +04:00
internal override object[] GetMethodAnnotations(MethodWrapper mw)
{
MethodBase mb = mw.GetMethod();
if(mb.DeclaringType.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
return mb.GetCustomAttributes(false);
2006-04-20 11:30:59 +04:00
}
internal override object[][] GetParameterAnnotations(MethodWrapper mw)
{
MethodBase mb = mw.GetMethod();
if(mb.DeclaringType.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
ParameterInfo[] parameters = mb.GetParameters();
int skip = 0;
if(mb.IsStatic && !mw.IsStatic && mw.Name != "<init>")
{
skip = 1;
}
int skipEnd = 0;
if(mw.HasCallerID)
{
skipEnd = 1;
}
object[][] attribs = new object[parameters.Length - skip - skipEnd][];
for(int i = skip; i < parameters.Length - skipEnd; i++)
2006-04-20 11:30:59 +04:00
{
attribs[i - skip] = parameters[i].GetCustomAttributes(false);
2006-04-20 11:30:59 +04:00
}
return attribs;
}
internal override object[] GetFieldAnnotations(FieldWrapper fw)
{
2006-10-04 13:03:18 +04:00
FieldInfo field = fw.GetField();
if(field != null)
{
if (field.DeclaringType.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
2006-10-04 13:03:18 +04:00
return field.GetCustomAttributes(false);
}
GetterFieldWrapper getter = fw as GetterFieldWrapper;
if(getter != null)
{
if (getter.GetGetter().DeclaringType.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
2006-10-04 13:03:18 +04:00
return getter.GetGetter().GetCustomAttributes(false);
}
CompiledPropertyFieldWrapper prop = fw as CompiledPropertyFieldWrapper;
if(prop != null)
{
if (prop.GetProperty().DeclaringType.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
return prop.GetProperty().GetCustomAttributes(false);
}
2006-10-04 13:03:18 +04:00
return new object[0];
2006-04-20 11:30:59 +04:00
}
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2005-11-01 17:01:42 +03:00
private class CompiledAnnotation : Annotation
{
private Type type;
internal CompiledAnnotation(Type type)
{
this.type = type;
}
2006-04-20 11:30:59 +04:00
private CustomAttributeBuilder MakeCustomAttributeBuilder(object annotation)
{
return new CustomAttributeBuilder(type.GetConstructor(new Type[] { typeof(object[]) }), new object[] { annotation });
}
internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation)
2005-11-01 17:01:42 +03:00
{
annotation = QualifyClassNames(loader, annotation);
2006-04-20 11:30:59 +04:00
tb.SetCustomAttribute(MakeCustomAttributeBuilder(annotation));
}
internal override void Apply(ClassLoaderWrapper loader, ConstructorBuilder cb, object annotation)
2006-04-20 11:30:59 +04:00
{
annotation = QualifyClassNames(loader, annotation);
2006-04-20 11:30:59 +04:00
cb.SetCustomAttribute(MakeCustomAttributeBuilder(annotation));
}
internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation)
2006-04-20 11:30:59 +04:00
{
annotation = QualifyClassNames(loader, annotation);
2006-04-20 11:30:59 +04:00
mb.SetCustomAttribute(MakeCustomAttributeBuilder(annotation));
}
internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation)
2006-04-20 11:30:59 +04:00
{
annotation = QualifyClassNames(loader, annotation);
2006-04-20 11:30:59 +04:00
fb.SetCustomAttribute(MakeCustomAttributeBuilder(annotation));
}
internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation)
2006-04-20 11:30:59 +04:00
{
annotation = QualifyClassNames(loader, annotation);
2006-04-20 11:30:59 +04:00
pb.SetCustomAttribute(MakeCustomAttributeBuilder(annotation));
2005-11-01 17:01:42 +03:00
}
2006-06-20 18:31:56 +04:00
internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation)
2006-06-20 18:31:56 +04:00
{
annotation = QualifyClassNames(loader, annotation);
2006-06-20 18:31:56 +04:00
ab.SetCustomAttribute(MakeCustomAttributeBuilder(annotation));
}
internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation)
{
annotation = QualifyClassNames(loader, annotation);
pb.SetCustomAttribute(MakeCustomAttributeBuilder(annotation));
}
2005-11-01 17:01:42 +03:00
}
internal override Annotation Annotation
{
get
{
2006-04-11 18:59:43 +04:00
string annotationAttribute = AttributeHelper.GetAnnotationAttributeType(type);
if(annotationAttribute != null)
2005-11-01 17:01:42 +03:00
{
2006-04-11 18:59:43 +04:00
return new CompiledAnnotation(type.Assembly.GetType(annotationAttribute, true));
2005-11-01 17:01:42 +03:00
}
return null;
}
}
2006-05-04 12:09:56 +04:00
2006-12-28 10:46:21 +03:00
internal override Type EnumType
{
get
{
if((this.Modifiers & Modifiers.Enum) != 0)
{
return type.GetNestedType("__Enum");
}
return null;
}
}
2006-05-04 12:09:56 +04:00
internal override string GetSourceFileName()
{
object[] attr = type.GetCustomAttributes(typeof(SourceFileAttribute), false);
if(attr.Length == 1)
{
return ((SourceFileAttribute)attr[0]).SourceFile;
}
if(type.Module.IsDefined(typeof(SourceFileAttribute), false))
{
return type.Name + ".java";
}
return null;
}
internal override int GetSourceLineNumber(MethodBase mb, int ilOffset)
{
object[] attr = mb.GetCustomAttributes(typeof(LineNumberTableAttribute), false);
if(attr.Length == 1)
{
return ((LineNumberTableAttribute)attr[0]).GetLineNumber(ilOffset);
}
return -1;
}
2005-12-07 12:06:32 +03:00
#endif
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
sealed class DotNetTypeWrapper : TypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
private const string NamePrefix = "cli.";
2005-08-25 13:36:36 +04:00
internal const string DelegateInterfaceSuffix = "$Method";
2006-06-15 16:29:11 +04:00
internal const string AttributeAnnotationSuffix = "$Annotation";
internal const string AttributeAnnotationReturnValueSuffix = "$__ReturnValue";
internal const string AttributeAnnotationMultipleSuffix = "$__Multiple";
2007-01-04 10:46:38 +03:00
internal const string EnumEnumSuffix = "$__Enum";
internal const string GenericEnumEnumTypeName = "ikvm.internal.EnumEnum`1";
internal const string GenericDelegateInterfaceTypeName = "ikvm.internal.DelegateInterface`1";
internal const string GenericAttributeAnnotationTypeName = "ikvm.internal.AttributeAnnotation`1";
internal const string GenericAttributeAnnotationReturnValueTypeName = "ikvm.internal.AttributeAnnotationReturnValue`1";
internal const string GenericAttributeAnnotationMultipleTypeName = "ikvm.internal.AttributeAnnotationMultiple`1";
2005-06-01 13:49:30 +04:00
private readonly Type type;
private TypeWrapper[] innerClasses;
private TypeWrapper outerClass;
private TypeWrapper[] interfaces;
private static Modifiers GetModifiers(Type type)
2003-10-17 12:08:31 +04:00
{
2005-06-01 13:49:30 +04:00
Modifiers modifiers = 0;
if(type.IsPublic)
2005-05-23 12:24:07 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers |= Modifiers.Public;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if(type.IsNestedPublic)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers |= Modifiers.Static;
if(IsVisible(type))
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers |= Modifiers.Public;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
else if(type.IsNestedPrivate)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers |= Modifiers.Private | Modifiers.Static;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if(type.IsNestedFamily || type.IsNestedFamORAssem)
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
modifiers |= Modifiers.Protected | Modifiers.Static;
}
else if(type.IsNestedAssembly || type.IsNestedFamANDAssem)
{
modifiers |= Modifiers.Static;
2004-04-23 18:21:43 +04:00
}
2003-08-26 15:24:17 +04:00
2005-06-01 13:49:30 +04:00
if(type.IsSealed)
{
modifiers |= Modifiers.Final;
}
else if(type.IsAbstract) // we can't be abstract if we're final
{
modifiers |= Modifiers.Abstract;
}
if(type.IsInterface)
{
modifiers |= Modifiers.Interface;
}
return modifiers;
2003-08-26 15:24:17 +04:00
}
2005-06-01 13:49:30 +04:00
// NOTE when this is called on a remapped type, the "warped" underlying type name is returned.
// E.g. GetName(typeof(object)) returns "cli.System.Object".
internal static string GetName(Type type)
2003-08-26 15:24:17 +04:00
{
2007-01-16 13:14:47 +03:00
Debug.Assert(!type.Name.EndsWith("[]") && !AttributeHelper.IsJavaModule(type.Module));
2003-08-26 15:24:17 +04:00
2006-01-23 13:18:44 +03:00
string name = type.FullName;
if(name == null)
{
2006-07-26 11:57:18 +04:00
// generic type parameters don't have a full name
2006-01-23 13:18:44 +03:00
return null;
}
2007-11-26 12:01:35 +03:00
if(type.ContainsGenericParameters)
2006-07-26 11:57:18 +04:00
{
// open generic types are not visible
return null;
}
2007-11-26 12:01:35 +03:00
if(type.IsGenericType)
2006-07-26 11:57:18 +04:00
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
2007-11-26 12:01:35 +03:00
sb.Append(MangleTypeName(type.GetGenericTypeDefinition().FullName));
2006-07-26 11:57:18 +04:00
sb.Append("_$$$_");
string sep = "";
2007-11-26 12:01:35 +03:00
foreach(Type t1 in type.GetGenericArguments())
2006-07-26 11:57:18 +04:00
{
Type t = t1;
2006-07-26 11:57:18 +04:00
sb.Append(sep);
// NOTE we can't use ClassLoaderWrapper.GetWrapperFromType() here to get t's name,
// because we might be resolving a generic type that refers to a type that is in
// the process of being constructed.
//
// For example:
// class Base<T> { }
// class Derived : Base<Derived> { }
//
while(ClassLoaderWrapper.IsVector(t))
{
t = t.GetElementType();
2006-07-26 11:57:18 +04:00
sb.Append('A');
}
if(PrimitiveTypeWrapper.IsPrimitiveType(t))
2006-07-26 11:57:18 +04:00
{
sb.Append(ClassLoaderWrapper.GetWrapperFromType(t).SigName);
2006-07-26 11:57:18 +04:00
}
else
{
string s;
if(ClassLoaderWrapper.IsRemappedType(t))
{
s = ClassLoaderWrapper.GetWrapperFromType(t).Name;
}
else if(ClassLoaderWrapper.IsDynamicType(t) || AttributeHelper.IsJavaModule(t.Module))
{
s = CompiledTypeWrapper.GetName(t);
}
else
{
s = DotNetTypeWrapper.GetName(t);
}
// only do the mangling for non-generic types (because we don't want to convert
// the double underscores in two adjacent _$$$_ or _$$$$_ markers)
if (s.IndexOf("_$$$_") == -1)
{
s = s.Replace("__", "$$005F$$005F");
s = s.Replace(".", "__");
}
2006-07-26 11:57:18 +04:00
sb.Append('L').Append(s);
}
sep = "_$$_";
}
sb.Append("_$$$$_");
return sb.ToString();
}
if(AttributeHelper.IsNoPackagePrefix(type)
&& name.IndexOf('$') == -1)
2004-08-17 13:05:21 +04:00
{
2006-01-23 13:18:44 +03:00
return name.Replace('+', '$');
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
2006-01-23 13:18:44 +03:00
return MangleTypeName(name);
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private static string MangleTypeName(string name)
2004-08-17 13:05:21 +04:00
{
2005-06-22 17:02:03 +04:00
System.Text.StringBuilder sb = new System.Text.StringBuilder(NamePrefix, NamePrefix.Length + name.Length);
2005-06-27 13:06:57 +04:00
bool escape = false;
bool nested = false;
2005-06-22 17:02:03 +04:00
for(int i = 0; i < name.Length; i++)
{
char c = name[i];
2005-06-27 13:06:57 +04:00
if(c == '+' && !escape && (sb.Length == 0 || sb[sb.Length - 1] != '$'))
2005-06-22 17:02:03 +04:00
{
nested = true;
2005-06-22 17:02:03 +04:00
sb.Append('$');
}
2005-06-27 13:06:57 +04:00
else if("_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".IndexOf(c) != -1
|| (c == '.' && !escape && !nested))
2005-06-22 17:02:03 +04:00
{
sb.Append(c);
}
else
{
2005-06-27 13:06:57 +04:00
sb.Append("$$");
2005-06-22 17:02:03 +04:00
sb.Append(string.Format("{0:X4}", (int)c));
}
2005-06-27 13:06:57 +04:00
if(c == '\\')
{
escape = !escape;
}
else
{
escape = false;
}
2005-06-22 17:02:03 +04:00
}
return sb.ToString();
2004-08-17 13:05:21 +04:00
}
2005-06-22 17:02:03 +04:00
// NOTE if the name is not a valid mangled type name, no demangling is done and the
// original string is returned
2006-07-26 11:57:18 +04:00
// NOTE we don't enforce canonical form, this is not required, because we cannot
// guarantee it for unprefixed names anyway, so the caller is responsible for
// ensuring that the original name was in fact the canonical name.
2006-07-21 14:18:13 +04:00
internal static string DemangleTypeName(string name)
2004-08-17 13:05:21 +04:00
{
2006-07-26 11:57:18 +04:00
if(!name.StartsWith(NamePrefix))
2005-06-01 13:49:30 +04:00
{
2006-07-26 11:57:18 +04:00
return name.Replace('$', '+');
2005-06-22 17:02:03 +04:00
}
2006-07-26 11:57:18 +04:00
System.Text.StringBuilder sb = new System.Text.StringBuilder(name.Length - NamePrefix.Length);
for(int i = NamePrefix.Length; i < name.Length; i++)
2005-06-22 17:02:03 +04:00
{
char c = name[i];
if(c == '$')
{
2006-07-26 11:57:18 +04:00
if(i + 1 < name.Length && name[i + 1] != '$')
2005-06-22 17:02:03 +04:00
{
2005-06-27 13:06:57 +04:00
sb.Append('+');
2005-06-22 17:02:03 +04:00
}
2005-06-27 13:06:57 +04:00
else
2005-06-22 17:02:03 +04:00
{
2005-06-27 13:06:57 +04:00
i++;
2006-07-26 11:57:18 +04:00
if(i + 5 > name.Length)
2005-06-27 13:06:57 +04:00
{
return name;
}
int digit0 = "0123456789ABCDEF".IndexOf(name[++i]);
int digit1 = "0123456789ABCDEF".IndexOf(name[++i]);
int digit2 = "0123456789ABCDEF".IndexOf(name[++i]);
int digit3 = "0123456789ABCDEF".IndexOf(name[++i]);
if(digit0 == -1 || digit1 == -1 || digit2 == -1 || digit3 == -1)
{
return name;
}
sb.Append((char)((digit0 << 12) + (digit1 << 8) + (digit2 << 4) + digit3));
2005-06-22 17:02:03 +04:00
}
}
else
{
sb.Append(c);
}
}
return sb.ToString();
2004-08-17 13:05:21 +04:00
}
2006-05-15 13:08:01 +04:00
// TODO from a perf pov it may be better to allow creation of TypeWrappers,
// but to simply make sure they don't have ClassObject
internal static bool IsAllowedOutside(Type type)
{
// SECURITY we never expose types from IKVM.Runtime, because doing so would lead to a security hole,
// since the reflection implementation lives inside this assembly, all internal members would
// be accessible through Java reflection.
#if !FIRST_PASS && !STATIC_COMPILER
2006-05-15 13:08:01 +04:00
if(type.Assembly == typeof(DotNetTypeWrapper).Assembly)
{
return false;
}
2007-12-28 17:36:30 +03:00
if(type.Assembly == IKVM.NativeCode.java.lang.SecurityManager.jniAssembly)
{
return false;
}
#endif
2007-11-26 12:01:35 +03:00
if(type.ContainsGenericParameters)
2006-05-15 13:08:01 +04:00
{
return false;
}
return true;
}
private class DelegateInnerClassTypeWrapper : TypeWrapper
{
private readonly Type fakeType;
2006-05-15 13:08:01 +04:00
2006-07-26 18:16:52 +04:00
internal DelegateInnerClassTypeWrapper(string name, Type delegateType, ClassLoaderWrapper classLoader)
2006-05-15 13:08:01 +04:00
: base(Modifiers.Public | Modifiers.Interface | Modifiers.Abstract, name, null)
{
#if STATIC_COMPILER
this.fakeType = FakeTypes.GetDelegateType(delegateType);
#elif !FIRST_PASS
this.fakeType = typeof(ikvm.@internal.DelegateInterface<>).MakeGenericType(delegateType);
#endif
2006-05-15 13:08:01 +04:00
MethodInfo invoke = delegateType.GetMethod("Invoke");
ParameterInfo[] parameters = invoke.GetParameters();
2006-08-26 17:00:50 +04:00
TypeWrapper[] argTypeWrappers = new TypeWrapper[parameters.Length];
2006-05-15 13:08:01 +04:00
System.Text.StringBuilder sb = new System.Text.StringBuilder("(");
2006-08-26 17:00:50 +04:00
for(int i = 0; i < parameters.Length; i++)
2006-05-15 13:08:01 +04:00
{
2006-08-26 17:00:50 +04:00
argTypeWrappers[i] = ClassLoaderWrapper.GetWrapperFromType(parameters[i].ParameterType);
2006-05-15 13:08:01 +04:00
sb.Append(argTypeWrappers[i].SigName);
}
TypeWrapper returnType = ClassLoaderWrapper.GetWrapperFromType(invoke.ReturnType);
sb.Append(")").Append(returnType.SigName);
2006-08-26 17:00:50 +04:00
MethodWrapper invokeMethod = new DynamicOnlyMethodWrapper(this, "Invoke", sb.ToString(), returnType, argTypeWrappers);
2006-05-15 13:08:01 +04:00
SetMethods(new MethodWrapper[] { invokeMethod });
SetFields(FieldWrapper.EmptyArray);
}
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
return ClassLoaderWrapper.GetWrapperFromType(fakeType.GetGenericArguments()[0]);
2006-05-15 13:08:01 +04:00
}
}
internal override void Finish()
{
}
internal override ClassLoaderWrapper GetClassLoader()
{
return DeclaringTypeWrapper.GetClassLoader();
}
internal override string[] GetEnclosingMethod()
{
return null;
}
internal override string GetGenericFieldSignature(FieldWrapper fw)
{
return null;
}
internal override string GetGenericMethodSignature(MethodWrapper mw)
{
return null;
}
internal override string GetGenericSignature()
{
return null;
}
internal override TypeWrapper[] InnerClasses
{
get
{
return TypeWrapper.EmptyArray;
}
}
internal override TypeWrapper[] Interfaces
{
get
{
return TypeWrapper.EmptyArray;
}
}
internal override Type TypeAsTBD
{
get
{
return fakeType;
2006-08-26 17:00:50 +04:00
}
}
}
private class DynamicOnlyMethodWrapper : MethodWrapper
{
internal DynamicOnlyMethodWrapper(TypeWrapper declaringType, string name, string sig, TypeWrapper returnType, TypeWrapper[] parameterTypes)
: base(declaringType, name, sig, null, returnType, parameterTypes, Modifiers.Public | Modifiers.Abstract, MemberFlags.None)
{
}
internal override bool IsDynamicOnly
{
get
{
return true;
}
}
#if !STATIC_COMPILER && !FIRST_PASS
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
{
return TypeWrapper.FromClass(NativeCode.ikvm.runtime.Util.getClassFromObject(obj))
.GetMethodWrapper(this.Name, this.Signature, true)
.Invoke(obj, args, false, callerID);
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2006-05-15 13:08:01 +04:00
}
2007-01-04 10:46:38 +03:00
private class EnumEnumTypeWrapper : TypeWrapper
{
private readonly Type fakeType;
2007-01-04 10:46:38 +03:00
internal EnumEnumTypeWrapper(string name, Type enumType)
: base(Modifiers.Public | Modifiers.Enum | Modifiers.Final, name, ClassLoaderWrapper.LoadClassCritical("java.lang.Enum"))
{
#if STATIC_COMPILER
this.fakeType = FakeTypes.GetEnumType(enumType);
#elif !FIRST_PASS
if(enumType.Assembly.ReflectionOnly)
{
TypeWrapper decl = ClassLoaderWrapper.GetWrapperFromType(enumType);
TypeWrapperFactory factory = ClassLoaderWrapper.GetBootstrapClassLoader().GetTypeWrapperFactory();
string basename = "<ReflectionOnlyType>" + enumType.FullName;
name = basename;
int index = 0;
while(!factory.ReserveName(name))
{
name = basename + (++index);
}
enumType = factory.ModuleBuilder.DefineEnum(name, TypeAttributes.Public, typeof(int)).CreateType();
ClassLoaderWrapper.SetWrapperForType(enumType, decl);
}
this.fakeType = typeof(ikvm.@internal.EnumEnum<>).MakeGenericType(enumType);
#endif
2007-01-04 10:46:38 +03:00
}
private class EnumFieldWrapper : FieldWrapper
{
private readonly int ordinal;
private object val;
internal EnumFieldWrapper(TypeWrapper tw, string name, int ordinal)
: base(tw, tw, name, tw.SigName, Modifiers.Public | Modifiers.Static | Modifiers.Final | Modifiers.Enum, null, MemberFlags.None)
{
this.ordinal = ordinal;
}
internal override object GetValue(object unused)
{
if(val == null)
2007-01-04 10:46:38 +03:00
{
System.Threading.Interlocked.CompareExchange(ref val, Activator.CreateInstance(this.DeclaringType.TypeAsTBD, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new object[] { this.Name, ordinal }, null), null);
2007-01-04 10:46:38 +03:00
}
return val;
}
protected override void EmitGetImpl(CodeEmitter ilgen)
2007-01-04 10:46:38 +03:00
{
// TODO we should throw a NoSuchFieldError if at runtime we find out that the "field" doesn't exist
ilgen.Emit(OpCodes.Ldtoken, this.DeclaringType.TypeAsTBD);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.GetClassFromTypeHandle);
ilgen.Emit(OpCodes.Castclass, CoreClasses.java.lang.Class.Wrapper.TypeAsTBD);
2007-01-04 10:46:38 +03:00
ilgen.Emit(OpCodes.Ldstr, this.Name);
this.DeclaringType.BaseTypeWrapper.GetMethodWrapper("valueOf", "(Ljava.lang.Class;Ljava.lang.String;)Ljava.lang.Enum;", false).EmitCall(ilgen);
ilgen.Emit(OpCodes.Castclass, this.DeclaringType.TypeAsTBD);
2007-01-04 10:46:38 +03:00
}
protected override void EmitSetImpl(CodeEmitter ilgen)
2007-01-04 10:46:38 +03:00
{
}
}
2007-01-04 15:54:10 +03:00
private class EnumValuesMethodWrapper : MethodWrapper
{
internal EnumValuesMethodWrapper(TypeWrapper declaringType)
: base(declaringType, "values", "()[" + declaringType.SigName, null, declaringType.MakeArrayType(1), TypeWrapper.EmptyArray, Modifiers.Public | Modifiers.Static, MemberFlags.None)
{
}
internal override bool IsDynamicOnly
{
get
{
return true;
}
}
#if !STATIC_COMPILER && !FIRST_PASS
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2007-01-04 15:54:10 +03:00
{
FieldWrapper[] values = this.DeclaringType.GetFields();
object[] array = (object[])Array.CreateInstance(this.DeclaringType.TypeAsArrayType, values.Length);
for(int i = 0; i < values.Length; i++)
{
array[i] = values[i].GetValue(null);
}
return array;
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2007-01-04 15:54:10 +03:00
}
private class EnumValueOfMethodWrapper : MethodWrapper
{
internal EnumValueOfMethodWrapper(TypeWrapper declaringType)
: base(declaringType, "valueOf", "(Ljava.lang.String;)" + declaringType.SigName, null, declaringType, new TypeWrapper[] { CoreClasses.java.lang.String.Wrapper }, Modifiers.Public | Modifiers.Static, MemberFlags.None)
{
}
internal override bool IsDynamicOnly
{
get
{
return true;
}
}
#if !STATIC_COMPILER && !FIRST_PASS
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2007-01-04 15:54:10 +03:00
{
FieldWrapper[] values = this.DeclaringType.GetFields();
for(int i = 0; i < values.Length; i++)
{
if(values[i].Name.Equals(args[0]))
{
return values[i].GetValue(null);
}
}
throw new java.lang.IllegalArgumentException("" + args[0]);
2007-01-04 15:54:10 +03:00
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2007-01-04 15:54:10 +03:00
}
2007-01-04 10:46:38 +03:00
protected override void LazyPublishMembers()
{
ArrayList fields = new ArrayList();
int ordinal = 0;
foreach(FieldInfo field in this.DeclaringTypeWrapper.TypeAsTBD.GetFields(BindingFlags.Static | BindingFlags.Public))
2007-01-04 10:46:38 +03:00
{
if(field.IsLiteral)
{
fields.Add(new EnumFieldWrapper(this, field.Name, ordinal++));
}
}
// TODO if the enum already has an __unspecified value, rename this one
fields.Add(new EnumFieldWrapper(this, "__unspecified", ordinal++));
SetFields((FieldWrapper[])fields.ToArray(typeof(FieldWrapper)));
2007-01-04 15:54:10 +03:00
SetMethods(new MethodWrapper[] { new EnumValuesMethodWrapper(this), new EnumValueOfMethodWrapper(this) });
2007-01-04 10:46:38 +03:00
base.LazyPublishMembers();
}
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
return ClassLoaderWrapper.GetWrapperFromType(fakeType.GetGenericArguments()[0]);
2007-01-04 10:46:38 +03:00
}
}
internal override void Finish()
{
}
internal override ClassLoaderWrapper GetClassLoader()
{
return DeclaringTypeWrapper.GetClassLoader();
}
internal override string[] GetEnclosingMethod()
{
return null;
}
internal override string GetGenericFieldSignature(FieldWrapper fw)
{
return null;
}
internal override string GetGenericMethodSignature(MethodWrapper mw)
{
return null;
}
internal override string GetGenericSignature()
{
return null;
}
internal override TypeWrapper[] InnerClasses
{
get
{
return TypeWrapper.EmptyArray;
}
}
internal override TypeWrapper[] Interfaces
{
get
{
return TypeWrapper.EmptyArray;
}
}
internal override Type TypeAsTBD
{
get
{
return fakeType;
2007-01-04 10:46:38 +03:00
}
}
}
private abstract class AttributeAnnotationTypeWrapperBase : TypeWrapper
{
internal AttributeAnnotationTypeWrapperBase(string name)
: base(Modifiers.Public | Modifiers.Interface | Modifiers.Abstract | Modifiers.Annotation, name, null)
{
}
internal sealed override void Finish()
{
}
internal sealed override ClassLoaderWrapper GetClassLoader()
{
return DeclaringTypeWrapper.GetClassLoader();
}
internal sealed override string[] GetEnclosingMethod()
{
return null;
}
internal sealed override string GetGenericFieldSignature(FieldWrapper fw)
{
return null;
}
internal sealed override string GetGenericMethodSignature(MethodWrapper mw)
{
return null;
}
internal sealed override string GetGenericSignature()
{
return null;
}
internal sealed override TypeWrapper[] Interfaces
{
get
{
return new TypeWrapper[] { ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName("java.lang.annotation.Annotation") };
}
}
}
private sealed class AttributeAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase
2006-06-15 16:29:11 +04:00
{
private readonly Type fakeType;
private readonly Type attributeType;
private TypeWrapper[] innerClasses;
2006-06-15 16:29:11 +04:00
internal AttributeAnnotationTypeWrapper(string name, Type attributeType)
: base(name)
2006-06-15 16:29:11 +04:00
{
#if STATIC_COMPILER
this.fakeType = FakeTypes.GetAttributeType(attributeType);
#elif !FIRST_PASS
this.fakeType = typeof(ikvm.@internal.AttributeAnnotation<>).MakeGenericType(attributeType);
#endif
2006-06-15 16:29:11 +04:00
this.attributeType = attributeType;
}
private static bool IsSupportedType(Type type)
2006-06-15 16:29:11 +04:00
{
// Java annotations only support one-dimensional arrays
if(type.IsArray)
2006-06-15 16:29:11 +04:00
{
type = type.GetElementType();
}
return type == typeof(string)
|| type == typeof(bool)
|| type == typeof(byte)
|| type == typeof(char)
|| type == typeof(short)
|| type == typeof(int)
|| type == typeof(float)
|| type == typeof(long)
|| type == typeof(double)
|| type == typeof(Type)
|| type.IsEnum;
}
internal static void GetConstructors(Type type, out ConstructorInfo defCtor, out ConstructorInfo singleOneArgCtor)
{
defCtor = null;
int oneArgCtorCount = 0;
ConstructorInfo oneArgCtor = null;
foreach(ConstructorInfo ci in type.GetConstructors(BindingFlags.Public | BindingFlags.Instance))
{
ParameterInfo[] args = ci.GetParameters();
if(args.Length == 0)
2006-06-15 16:29:11 +04:00
{
defCtor = ci;
}
else if(args.Length == 1)
{
// HACK special case for p/invoke StructLayout attribute
if(type == typeof(System.Runtime.InteropServices.StructLayoutAttribute) && args[0].ParameterType == typeof(short))
{
// we skip this constructor, so that the other one will be visible
continue;
}
if(IsSupportedType(args[0].ParameterType))
2006-06-15 16:29:11 +04:00
{
oneArgCtor = ci;
oneArgCtorCount++;
}
else
{
// set to two to make sure we don't see the oneArgCtor as viable
oneArgCtorCount = 2;
2006-06-15 16:29:11 +04:00
}
}
}
singleOneArgCtor = oneArgCtorCount == 1 ? oneArgCtor : null;
}
private class AttributeAnnotationMethodWrapper : DynamicOnlyMethodWrapper
{
private bool optional;
internal AttributeAnnotationMethodWrapper(AttributeAnnotationTypeWrapper tw, string name, Type type, bool optional)
: this(tw, name, MapType(type, false), optional)
2006-06-20 18:31:56 +04:00
{
}
private static TypeWrapper MapType(Type type, bool isArray)
{
if(type == typeof(string))
2006-06-20 18:31:56 +04:00
{
return CoreClasses.java.lang.String.Wrapper;
}
else if(type == typeof(bool))
{
return PrimitiveTypeWrapper.BOOLEAN;
}
else if(type == typeof(byte))
{
return PrimitiveTypeWrapper.BYTE;
}
else if(type == typeof(char))
{
return PrimitiveTypeWrapper.CHAR;
}
else if(type == typeof(short))
{
return PrimitiveTypeWrapper.SHORT;
}
else if(type == typeof(int))
{
return PrimitiveTypeWrapper.INT;
}
else if(type == typeof(float))
{
return PrimitiveTypeWrapper.FLOAT;
}
else if(type == typeof(long))
{
return PrimitiveTypeWrapper.LONG;
}
else if(type == typeof(double))
{
return PrimitiveTypeWrapper.DOUBLE;
}
else if(type == typeof(Type))
{
return CoreClasses.java.lang.Class.Wrapper;
}
else if (type.IsEnum)
{
foreach (TypeWrapper tw in ClassLoaderWrapper.GetWrapperFromType(type).InnerClasses)
2007-01-04 10:46:38 +03:00
{
if (tw is EnumEnumTypeWrapper)
2007-01-04 10:46:38 +03:00
{
if (!isArray && AttributeHelper.IsDefined(type, typeof(FlagsAttribute)))
2007-01-04 10:46:38 +03:00
{
return tw.MakeArrayType(1);
2007-01-04 10:46:38 +03:00
}
return tw;
2007-01-04 10:46:38 +03:00
}
}
throw new InvalidOperationException();
}
else if(!isArray && type.IsArray)
{
return MapType(type.GetElementType(), true).MakeArrayType(1);
}
else
{
throw new NotImplementedException();
}
}
private AttributeAnnotationMethodWrapper(AttributeAnnotationTypeWrapper tw, string name, TypeWrapper returnType, bool optional)
: base(tw, name, "()" + returnType.SigName, returnType, TypeWrapper.EmptyArray)
{
this.optional = optional;
}
internal bool IsOptional
{
get
{
return optional;
2006-06-20 18:31:56 +04:00
}
}
2006-06-15 16:29:11 +04:00
}
protected override void LazyPublishMembers()
2006-06-20 18:31:56 +04:00
{
ArrayList methods = new ArrayList();
ConstructorInfo defCtor;
ConstructorInfo singleOneArgCtor;
GetConstructors(attributeType, out defCtor, out singleOneArgCtor);
if(singleOneArgCtor != null)
2006-06-20 18:31:56 +04:00
{
methods.Add(new AttributeAnnotationMethodWrapper(this, "value", singleOneArgCtor.GetParameters()[0].ParameterType, defCtor != null));
2006-06-20 18:31:56 +04:00
}
foreach(PropertyInfo pi in attributeType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
2006-06-20 18:31:56 +04:00
{
if(pi.CanRead && pi.CanWrite && IsSupportedType(pi.PropertyType))
{
methods.Add(new AttributeAnnotationMethodWrapper(this, pi.Name, pi.PropertyType, true));
}
2006-06-20 18:31:56 +04:00
}
foreach(FieldInfo fi in attributeType.GetFields(BindingFlags.Public | BindingFlags.Instance))
2007-01-04 10:46:38 +03:00
{
// TODO add other field validations to make sure it is appropriate
if(!fi.IsInitOnly && IsSupportedType(fi.FieldType))
{
methods.Add(new AttributeAnnotationMethodWrapper(this, fi.Name, fi.FieldType, true));
}
}
SetMethods((MethodWrapper[])methods.ToArray(typeof(MethodWrapper)));
base.LazyPublishMembers();
}
#if !STATIC_COMPILER && !FIRST_PASS
internal override object GetAnnotationDefault(MethodWrapper mw)
{
if(((AttributeAnnotationMethodWrapper)mw).IsOptional)
{
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)
{
return mw.ReturnType.GetFieldWrapper("__unspecified", mw.ReturnType.SigName).GetValue(null);
}
else if(mw.ReturnType.IsArray)
{
return Array.CreateInstance(mw.ReturnType.TypeAsArrayType, 0);
}
2007-01-04 10:46:38 +03:00
}
2006-06-20 18:31:56 +04:00
return null;
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2006-06-20 18:31:56 +04:00
2006-06-15 16:29:11 +04:00
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
return ClassLoaderWrapper.GetWrapperFromType(attributeType);
}
}
internal override Type TypeAsTBD
{
get
{
return fakeType;
}
}
private sealed class ReturnValueAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase
2006-06-15 16:29:11 +04:00
{
private readonly Type fakeType;
private readonly AttributeAnnotationTypeWrapper declaringType;
2006-06-15 16:29:11 +04:00
internal ReturnValueAnnotationTypeWrapper(AttributeAnnotationTypeWrapper declaringType)
: base(declaringType.Name + AttributeAnnotationReturnValueSuffix)
{
#if STATIC_COMPILER
this.fakeType = FakeTypes.GetAttributeReturnValueType(declaringType.attributeType);
#elif !FIRST_PASS
this.fakeType = typeof(ikvm.@internal.AttributeAnnotationReturnValue<>).MakeGenericType(declaringType.attributeType);
#endif
this.declaringType = declaringType;
}
2006-06-15 16:29:11 +04:00
protected override void LazyPublishMembers()
{
TypeWrapper tw = declaringType;
if(declaringType.GetAttributeUsage().AllowMultiple)
{
tw = tw.MakeArrayType(1);
}
SetMethods(new MethodWrapper[] { new DynamicOnlyMethodWrapper(this, "value", "()" + tw.SigName, tw, TypeWrapper.EmptyArray) });
SetFields(FieldWrapper.EmptyArray);
}
2006-06-15 16:29:11 +04:00
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
return declaringType;
}
}
2006-06-15 16:29:11 +04:00
internal override TypeWrapper[] InnerClasses
{
get
{
return TypeWrapper.EmptyArray;
}
}
2006-06-15 16:29:11 +04:00
internal override Type TypeAsTBD
{
get
{
return fakeType;
}
}
#if !STATIC_COMPILER && !FIRST_PASS
internal override object[] GetDeclaredAnnotations()
{
java.util.HashMap targetMap = new java.util.HashMap();
targetMap.put("value", new java.lang.annotation.ElementType[] { java.lang.annotation.ElementType.METHOD });
java.util.HashMap retentionMap = new java.util.HashMap();
retentionMap.put("value", java.lang.annotation.RetentionPolicy.RUNTIME);
return new object[] {
java.lang.reflect.Proxy.newProxyInstance(null, new java.lang.Class[] { typeof(java.lang.annotation.Target) }, new sun.reflect.annotation.AnnotationInvocationHandler(typeof(java.lang.annotation.Target), targetMap)),
java.lang.reflect.Proxy.newProxyInstance(null, new java.lang.Class[] { typeof(java.lang.annotation.Retention) }, new sun.reflect.annotation.AnnotationInvocationHandler(typeof(java.lang.annotation.Retention), retentionMap))
};
}
#endif
2006-06-15 16:29:11 +04:00
#if !COMPACT_FRAMEWORK
private class ReturnValueAnnotation : Annotation
2006-06-15 16:29:11 +04:00
{
private AttributeAnnotationTypeWrapper type;
internal ReturnValueAnnotation(AttributeAnnotationTypeWrapper type)
{
this.type = type;
}
internal override void ApplyReturnValue(ClassLoaderWrapper loader, MethodBuilder mb, ref ParameterBuilder pb, object annotation)
{
// TODO make sure the descriptor is correct
Annotation ann = type.Annotation;
object[] arr = (object[])annotation;
for(int i = 2; i < arr.Length; i += 2)
{
if("value".Equals(arr[i]))
{
if(pb == null)
{
pb = mb.DefineParameter(0, ParameterAttributes.None, null);
}
object[] value = (object[])arr[i + 1];
if(value[0].Equals(AnnotationDefaultAttribute.TAG_ANNOTATION))
{
ann.Apply(loader, pb, value);
}
else
{
for(int j = 1; j < value.Length; j++)
{
ann.Apply(loader, pb, value[j]);
}
}
break;
}
}
}
internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation)
{
}
internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation)
{
}
internal override void Apply(ClassLoaderWrapper loader, ConstructorBuilder cb, object annotation)
{
}
internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation)
{
}
internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation)
{
}
internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation)
{
}
internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation)
{
}
2006-06-15 16:29:11 +04:00
}
internal override Annotation Annotation
2006-06-15 16:29:11 +04:00
{
get
{
return new ReturnValueAnnotation(declaringType);
}
2006-06-15 16:29:11 +04:00
}
#endif
2006-06-15 16:29:11 +04:00
}
private sealed class MultipleAnnotationTypeWrapper : AttributeAnnotationTypeWrapperBase
2006-08-26 17:00:50 +04:00
{
private readonly Type fakeType;
private readonly AttributeAnnotationTypeWrapper declaringType;
internal MultipleAnnotationTypeWrapper(AttributeAnnotationTypeWrapper declaringType)
: base(declaringType.Name + AttributeAnnotationMultipleSuffix)
2006-08-26 17:00:50 +04:00
{
#if STATIC_COMPILER
this.fakeType = FakeTypes.GetAttributeMultipleType(declaringType.attributeType);
#elif !FIRST_PASS
this.fakeType = typeof(ikvm.@internal.AttributeAnnotationMultiple<>).MakeGenericType(declaringType.attributeType);
#endif
this.declaringType = declaringType;
2006-08-26 17:00:50 +04:00
}
protected override void LazyPublishMembers()
2006-06-15 16:29:11 +04:00
{
TypeWrapper tw = declaringType.MakeArrayType(1);
SetMethods(new MethodWrapper[] { new DynamicOnlyMethodWrapper(this, "value", "()" + tw.SigName, tw, TypeWrapper.EmptyArray) });
SetFields(FieldWrapper.EmptyArray);
}
internal override TypeWrapper DeclaringTypeWrapper
{
get
{
return declaringType;
}
}
internal override TypeWrapper[] InnerClasses
{
get
{
return TypeWrapper.EmptyArray;
}
}
internal override Type TypeAsTBD
{
get
{
return fakeType;
}
}
#if !STATIC_COMPILER
internal override object[] GetDeclaredAnnotations()
{
return declaringType.GetDeclaredAnnotations();
}
#endif
#if !COMPACT_FRAMEWORK
private class MultipleAnnotation : Annotation
{
private AttributeAnnotationTypeWrapper type;
internal MultipleAnnotation(AttributeAnnotationTypeWrapper type)
{
this.type = type;
}
private static object[] UnwrapArray(object annotation)
{
// TODO make sure the descriptor is correct
object[] arr = (object[])annotation;
for (int i = 2; i < arr.Length; i += 2)
{
if ("value".Equals(arr[i]))
{
object[] value = (object[])arr[i + 1];
object[] rc = new object[value.Length - 1];
Array.Copy(value, 1, rc, 0, rc.Length);
return rc;
}
}
return new object[0];
}
internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation)
{
Annotation annot = type.Annotation;
foreach(object ann in UnwrapArray(annotation))
{
annot.Apply(loader, mb, ann);
}
}
internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation)
{
Annotation annot = type.Annotation;
foreach (object ann in UnwrapArray(annotation))
{
annot.Apply(loader, ab, ann);
}
}
internal override void Apply(ClassLoaderWrapper loader, ConstructorBuilder cb, object annotation)
{
Annotation annot = type.Annotation;
foreach (object ann in UnwrapArray(annotation))
{
annot.Apply(loader, cb, ann);
}
}
internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation)
{
Annotation annot = type.Annotation;
foreach (object ann in UnwrapArray(annotation))
{
annot.Apply(loader, fb, ann);
}
}
internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation)
{
Annotation annot = type.Annotation;
foreach (object ann in UnwrapArray(annotation))
{
annot.Apply(loader, pb, ann);
}
}
internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation)
{
Annotation annot = type.Annotation;
foreach (object ann in UnwrapArray(annotation))
{
annot.Apply(loader, tb, ann);
}
}
internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation)
{
Annotation annot = type.Annotation;
foreach (object ann in UnwrapArray(annotation))
{
annot.Apply(loader, pb, ann);
}
}
2006-08-26 17:00:50 +04:00
}
internal override Annotation Annotation
{
get
{
return new MultipleAnnotation(declaringType);
}
}
#endif
2006-08-26 17:00:50 +04:00
}
internal override TypeWrapper[] InnerClasses
2006-08-26 17:00:50 +04:00
{
get
{
lock(this)
{
if(innerClasses == null)
{
ArrayList list = new ArrayList();
AttributeUsageAttribute attr = GetAttributeUsage();
if((attr.ValidOn & AttributeTargets.ReturnValue) != 0)
{
list.Add(GetClassLoader().RegisterInitiatingLoader(new ReturnValueAnnotationTypeWrapper(this)));
}
if(attr.AllowMultiple)
{
list.Add(GetClassLoader().RegisterInitiatingLoader(new MultipleAnnotationTypeWrapper(this)));
}
innerClasses = (TypeWrapper[])list.ToArray(typeof(TypeWrapper));
}
}
return innerClasses;
2006-06-15 16:29:11 +04:00
}
}
internal override bool IsFakeTypeContainer
{
get
{
return true;
}
}
private AttributeUsageAttribute GetAttributeUsage()
2007-01-04 10:46:38 +03:00
{
AttributeTargets validOn = AttributeTargets.All;
bool allowMultiple = false;
bool inherited = true;
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(attributeType))
{
if(cad.Constructor.DeclaringType == typeof(AttributeUsageAttribute))
{
if(cad.ConstructorArguments.Count == 1 && cad.ConstructorArguments[0].ArgumentType == typeof(AttributeTargets))
{
validOn = (AttributeTargets)cad.ConstructorArguments[0].Value;
}
foreach(CustomAttributeNamedArgument cana in cad.NamedArguments)
{
if (cana.MemberInfo.Name == "AllowMultiple")
{
allowMultiple = (bool)cana.TypedValue.Value;
}
else if(cana.MemberInfo.Name == "Inherited")
{
inherited = (bool)cana.TypedValue.Value;
}
}
}
}
AttributeUsageAttribute attr = new AttributeUsageAttribute(validOn);
attr.AllowMultiple = allowMultiple;
attr.Inherited = inherited;
return attr;
}
#if !STATIC_COMPILER && !FIRST_PASS
internal override object[] GetDeclaredAnnotations()
{
// note that AttributeUsageAttribute.Inherited does not map to java.lang.annotation.Inherited
AttributeTargets validOn = GetAttributeUsage().ValidOn;
List<java.lang.annotation.ElementType> targets = new List<java.lang.annotation.ElementType>();
if ((validOn & (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate | AttributeTargets.Assembly)) != 0)
{
targets.Add(java.lang.annotation.ElementType.TYPE);
}
if ((validOn & AttributeTargets.Constructor) != 0)
{
targets.Add(java.lang.annotation.ElementType.CONSTRUCTOR);
}
if ((validOn & AttributeTargets.Field) != 0)
{
targets.Add(java.lang.annotation.ElementType.FIELD);
}
if ((validOn & AttributeTargets.Method) != 0)
{
targets.Add(java.lang.annotation.ElementType.METHOD);
}
if ((validOn & AttributeTargets.Parameter) != 0)
{
targets.Add(java.lang.annotation.ElementType.PARAMETER);
}
java.util.HashMap targetMap = new java.util.HashMap();
targetMap.put("value", targets.ToArray());
java.util.HashMap retentionMap = new java.util.HashMap();
retentionMap.put("value", java.lang.annotation.RetentionPolicy.RUNTIME);
2007-01-04 10:46:38 +03:00
return new object[] {
java.lang.reflect.Proxy.newProxyInstance(null, new java.lang.Class[] { typeof(java.lang.annotation.Target) }, new sun.reflect.annotation.AnnotationInvocationHandler(typeof(java.lang.annotation.Target), targetMap)),
java.lang.reflect.Proxy.newProxyInstance(null, new java.lang.Class[] { typeof(java.lang.annotation.Retention) }, new sun.reflect.annotation.AnnotationInvocationHandler(typeof(java.lang.annotation.Retention), retentionMap))
};
2007-01-04 10:46:38 +03:00
}
#endif
2006-07-06 17:53:51 +04:00
#if !COMPACT_FRAMEWORK
2006-06-15 16:29:11 +04:00
private class AttributeAnnotation : Annotation
{
private Type type;
internal AttributeAnnotation(Type type)
{
this.type = type;
}
private static object ConvertValue(ClassLoaderWrapper loader, Type targetType, object obj)
2006-06-15 16:29:11 +04:00
{
if(targetType.IsEnum)
2006-06-15 16:29:11 +04:00
{
// TODO check the obj descriptor matches the type we expect
if(((object[])obj)[0].Equals(AnnotationDefaultAttribute.TAG_ARRAY))
{
object[] arr = (object[])obj;
string s = "";
string sep = "";
for(int i = 1; i < arr.Length; i++)
{
// TODO check the obj descriptor matches the type we expect
string val = ((object[])arr[i])[2].ToString();
if(val != "__unspecified")
{
s += sep + val;
sep = ", ";
}
}
if(s == "")
{
return Activator.CreateInstance(targetType);
}
return Enum.Parse(targetType, s);
}
else
{
string s = ((object[])obj)[2].ToString();
if(s == "__unspecified")
{
// TODO instead of this, we should probably return null and handle that
return Activator.CreateInstance(targetType);
}
return Enum.Parse(targetType, s);
}
2006-06-15 16:29:11 +04:00
}
else if(targetType == typeof(Type))
2006-06-15 16:29:11 +04:00
{
// TODO check the obj descriptor matches the type we expect
return loader.FieldTypeWrapperFromSig(((string)((object[])obj)[1]).Replace('/', '.')).TypeAsTBD;
2006-06-15 16:29:11 +04:00
}
else if(targetType.IsArray)
2006-06-20 18:31:56 +04:00
{
// TODO check the obj descriptor matches the type we expect
object[] arr = (object[])obj;
Type elementType = targetType.GetElementType();
Array targetArray = Array.CreateInstance(elementType, arr.Length - 1);
for(int i = 1; i < arr.Length; i++)
{
targetArray.SetValue(ConvertValue(loader, elementType, arr[i]), i - 1);
}
return targetArray;
}
else
{
return obj;
2006-06-20 18:31:56 +04:00
}
2006-06-15 16:29:11 +04:00
}
private CustomAttributeBuilder MakeCustomAttributeBuilder(ClassLoaderWrapper loader, object annotation)
2006-06-15 16:29:11 +04:00
{
object[] arr = (object[])annotation;
ConstructorInfo defCtor;
ConstructorInfo singleOneArgCtor;
object ctorArg = null;
GetConstructors(type, out defCtor, out singleOneArgCtor);
ArrayList properties = new ArrayList();
ArrayList propertyValues = new ArrayList();
ArrayList fields = new ArrayList();
ArrayList fieldValues = new ArrayList();
for(int i = 2; i < arr.Length; i += 2)
{
string name = (string)arr[i];
if(name == "value" && singleOneArgCtor != null)
{
ctorArg = ConvertValue(loader, singleOneArgCtor.GetParameters()[0].ParameterType, arr[i + 1]);
}
else
{
PropertyInfo pi = type.GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
if(pi != null)
{
properties.Add(pi);
propertyValues.Add(ConvertValue(loader, pi.PropertyType, arr[i + 1]));
}
else
{
FieldInfo fi = type.GetField(name, BindingFlags.Public | BindingFlags.Instance);
if(fi != null)
{
fields.Add(fi);
fieldValues.Add(ConvertValue(loader, fi.FieldType, arr[i + 1]));
}
}
}
}
if(ctorArg == null && defCtor == null)
{
// TODO required argument is missing
}
return new CustomAttributeBuilder(ctorArg == null ? defCtor : singleOneArgCtor,
ctorArg == null ? new object[0] : new object[] { ctorArg },
(PropertyInfo[])properties.ToArray(typeof(PropertyInfo)),
(object[])propertyValues.ToArray(),
(FieldInfo[])fields.ToArray(typeof(FieldInfo)),
(object[])fieldValues.ToArray());
}
internal override void Apply(ClassLoaderWrapper loader, TypeBuilder tb, object annotation)
{
if(type == typeof(System.Runtime.InteropServices.StructLayoutAttribute) && tb.BaseType != typeof(object))
{
// we have to handle this explicitly, because if we apply an illegal StructLayoutAttribute,
// TypeBuilder.CreateType() will later on throw an exception.
Tracer.Error(Tracer.Runtime, "StructLayoutAttribute cannot be applied to {0}, because it does not directly extend cli.System.Object", tb.FullName);
return;
}
tb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
2006-06-15 16:29:11 +04:00
}
internal override void Apply(ClassLoaderWrapper loader, ConstructorBuilder cb, object annotation)
2006-06-15 16:29:11 +04:00
{
cb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
2006-06-15 16:29:11 +04:00
}
internal override void Apply(ClassLoaderWrapper loader, MethodBuilder mb, object annotation)
2006-06-15 16:29:11 +04:00
{
mb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
2006-06-15 16:29:11 +04:00
}
internal override void Apply(ClassLoaderWrapper loader, FieldBuilder fb, object annotation)
2006-06-15 16:29:11 +04:00
{
fb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
2006-06-15 16:29:11 +04:00
}
internal override void Apply(ClassLoaderWrapper loader, ParameterBuilder pb, object annotation)
2006-06-15 16:29:11 +04:00
{
pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
2006-06-15 16:29:11 +04:00
}
2006-06-20 18:31:56 +04:00
internal override void Apply(ClassLoaderWrapper loader, AssemblyBuilder ab, object annotation)
2006-06-20 18:31:56 +04:00
{
ab.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
2006-06-20 18:31:56 +04:00
}
internal override void Apply(ClassLoaderWrapper loader, PropertyBuilder pb, object annotation)
{
pb.SetCustomAttribute(MakeCustomAttributeBuilder(loader, annotation));
}
2006-06-15 16:29:11 +04:00
}
internal override Annotation Annotation
{
get
{
return new AttributeAnnotation(attributeType);
}
}
2006-07-06 17:53:51 +04:00
#endif //!COMPACT_FRAMEWORK
2006-06-15 16:29:11 +04:00
}
2005-06-01 13:49:30 +04:00
internal static TypeWrapper GetWrapperFromDotNetType(Type type)
2004-10-04 23:30:53 +04:00
{
2006-08-14 11:57:03 +04:00
return ClassLoaderWrapper.GetAssemblyClassLoader(type.Assembly).GetWrapperFromAssemblyType(type);
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
private static TypeWrapper GetBaseTypeWrapper(Type type)
2004-10-04 23:30:53 +04:00
{
2005-06-01 13:49:30 +04:00
if(type.IsInterface)
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return null;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else if(ClassLoaderWrapper.IsRemappedType(type))
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
// Remapped types extend their alter ego
// (e.g. cli.System.Object must appear to be derived from java.lang.Object)
// except when they're sealed, of course.
if(type.IsSealed)
{
return CoreClasses.java.lang.Object.Wrapper;
}
return ClassLoaderWrapper.GetWrapperFromType(type);
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else if(ClassLoaderWrapper.IsRemappedType(type.BaseType))
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return GetWrapperFromDotNetType(type.BaseType);
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
else
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
return ClassLoaderWrapper.GetWrapperFromType(type.BaseType);
2004-12-21 13:26:51 +03:00
}
2004-10-04 23:30:53 +04:00
}
internal DotNetTypeWrapper(Type type, string name)
: base(GetModifiers(type), name, GetBaseTypeWrapper(type))
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
Debug.Assert(!(type.IsByRef), type.FullName);
Debug.Assert(!(type.IsPointer), type.FullName);
2007-01-16 13:14:47 +03:00
Debug.Assert(!(type.Name.EndsWith("[]")), type.FullName);
2005-06-01 13:49:30 +04:00
Debug.Assert(!(type is TypeBuilder), type.FullName);
2005-12-07 12:06:32 +03:00
Debug.Assert(!(AttributeHelper.IsJavaModule(type.Module)));
2005-06-01 13:49:30 +04:00
this.type = type;
2004-06-25 13:38:07 +04:00
}
2005-06-01 13:49:30 +04:00
internal override ClassLoaderWrapper GetClassLoader()
2004-06-25 13:38:07 +04:00
{
2007-11-26 12:01:35 +03:00
if(type.IsGenericType)
2006-07-26 14:33:52 +04:00
{
return ClassLoaderWrapper.GetGenericClassLoader(this);
}
2006-05-15 13:08:01 +04:00
return ClassLoaderWrapper.GetAssemblyClassLoader(type.Assembly);
2004-06-25 13:38:07 +04:00
}
2005-06-01 13:49:30 +04:00
private class DelegateMethodWrapper : MethodWrapper
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
private ConstructorInfo delegateConstructor;
2006-05-15 13:08:01 +04:00
private DelegateInnerClassTypeWrapper iface;
2005-06-01 13:49:30 +04:00
2006-05-15 13:08:01 +04:00
internal DelegateMethodWrapper(TypeWrapper declaringType, DelegateInnerClassTypeWrapper iface)
2005-06-01 13:49:30 +04:00
: base(declaringType, "<init>", "(" + iface.SigName + ")V", null, PrimitiveTypeWrapper.VOID, new TypeWrapper[] { iface }, Modifiers.Public, MemberFlags.None)
2004-12-21 13:26:51 +03:00
{
2006-05-15 13:08:01 +04:00
this.delegateConstructor = declaringType.TypeAsTBD.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) });
this.iface = iface;
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal override void EmitNewobj(CodeEmitter ilgen, MethodAnalyzer ma, int opcodeIndex)
2004-12-21 13:26:51 +03:00
{
2006-08-26 17:00:50 +04:00
TypeWrapper targetType = ma == null ? null : ma.GetStackTypeWrapper(opcodeIndex, 0);
if(targetType == null || targetType.IsInterface)
{
MethodInfo createDelegate = typeof(Delegate).GetMethod("CreateDelegate", new Type[] { typeof(Type), typeof(object), typeof(string) });
LocalBuilder targetObj = ilgen.DeclareLocal(typeof(object));
ilgen.Emit(OpCodes.Stloc, targetObj);
ilgen.Emit(OpCodes.Ldtoken, delegateConstructor.DeclaringType);
ilgen.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }));
ilgen.Emit(OpCodes.Ldloc, targetObj);
ilgen.Emit(OpCodes.Ldstr, "Invoke");
ilgen.Emit(OpCodes.Call, createDelegate);
ilgen.Emit(OpCodes.Castclass, delegateConstructor.DeclaringType);
}
else
{
ilgen.Emit(OpCodes.Dup);
// we know that a DelegateInnerClassTypeWrapper has only one method
Debug.Assert(iface.GetMethods().Length == 1);
MethodWrapper mw = targetType.GetMethodWrapper("Invoke", iface.GetMethods()[0].Signature, true);
// TODO linking here is not safe
mw.Link();
ilgen.Emit(OpCodes.Ldvirtftn, (MethodInfo)mw.GetMethod());
ilgen.Emit(OpCodes.Newobj, delegateConstructor);
}
2004-12-21 13:26:51 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
#if !STATIC_COMPILER && !FIRST_PASS
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO map exceptions
return Delegate.CreateDelegate(DeclaringType.TypeAsTBD, args[0], "Invoke");
2004-12-21 13:26:51 +03:00
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2005-06-01 13:49:30 +04:00
}
private class ByRefMethodWrapper : SmartMethodWrapper
{
#if !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
private bool[] byrefs;
#endif
2005-06-01 13:49:30 +04:00
private Type[] args;
internal ByRefMethodWrapper(Type[] args, bool[] byrefs, TypeWrapper declaringType, string name, string sig, MethodBase method, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, bool hideFromReflection)
: base(declaringType, name, sig, method, returnType, parameterTypes, modifiers, hideFromReflection ? MemberFlags.HideFromReflection : MemberFlags.None)
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
this.args = args;
#if !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
this.byrefs = byrefs;
#endif
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
protected override void CallImpl(CodeEmitter ilgen)
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
MethodBase mb = GetMethod();
MethodInfo mi = mb as MethodInfo;
if(mi != null)
{
ilgen.Emit(OpCodes.Call, mi);
}
else
{
ilgen.Emit(OpCodes.Call, (ConstructorInfo)mb);
}
2004-06-25 13:38:07 +04:00
}
2005-06-01 13:49:30 +04:00
protected override void CallvirtImpl(CodeEmitter ilgen)
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
ilgen.Emit(OpCodes.Callvirt, (MethodInfo)GetMethod());
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
protected override void NewobjImpl(CodeEmitter ilgen)
2004-06-25 13:38:07 +04:00
{
2005-06-01 13:49:30 +04:00
ilgen.Emit(OpCodes.Newobj, (ConstructorInfo)GetMethod());
2004-06-25 13:38:07 +04:00
}
2004-12-21 13:26:51 +03:00
protected override void PreEmit(CodeEmitter ilgen)
2005-06-01 13:49:30 +04:00
{
LocalBuilder[] locals = new LocalBuilder[args.Length];
for(int i = args.Length - 1; i >= 0; i--)
{
Type type = args[i];
if(type.IsByRef)
{
2006-07-05 12:46:56 +04:00
type = ArrayTypeWrapper.MakeArrayType(type.GetElementType(), 1);
2005-06-01 13:49:30 +04:00
}
locals[i] = ilgen.DeclareLocal(type);
ilgen.Emit(OpCodes.Stloc, locals[i]);
}
for(int i = 0; i < args.Length; i++)
{
ilgen.Emit(OpCodes.Ldloc, locals[i]);
if(args[i].IsByRef)
{
ilgen.Emit(OpCodes.Ldc_I4_0);
ilgen.Emit(OpCodes.Ldelema, args[i].GetElementType());
}
}
base.PreEmit(ilgen);
}
2005-12-07 12:06:32 +03:00
#endif
2004-06-25 13:38:07 +04:00
#if !STATIC_COMPILER && !FIRST_PASS
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2005-06-01 13:49:30 +04:00
{
object[] newargs = (object[])args.Clone();
for(int i = 0; i < newargs.Length; i++)
{
if(byrefs[i])
{
newargs[i] = ((Array)args[i]).GetValue(0);
}
}
try
{
return base.Invoke(obj, newargs, nonVirtual, callerID);
2005-06-01 13:49:30 +04:00
}
finally
{
for(int i = 0; i < newargs.Length; i++)
{
if(byrefs[i])
{
((Array)args[i]).SetValue(newargs[i], 0);
}
}
}
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
internal static bool IsVisible(Type type)
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
return type.IsPublic || (type.IsNestedPublic && IsVisible(type.DeclaringType));
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
private class EnumWrapMethodWrapper : MethodWrapper
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
internal EnumWrapMethodWrapper(DotNetTypeWrapper tw, TypeWrapper fieldType)
: base(tw, "wrap", "(" + fieldType.SigName + ")" + tw.SigName, null, tw, new TypeWrapper[] { fieldType }, Modifiers.Static | Modifiers.Public, MemberFlags.None)
{
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal override void EmitCall(CodeEmitter ilgen)
2005-06-01 13:49:30 +04:00
{
// We don't actually need to do anything here!
// The compiler will insert a boxing operation after calling us and that will
// result in our argument being boxed (since that's still sitting on the stack).
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
#if !STATIC_COMPILER && !FIRST_PASS
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
return Enum.ToObject(DeclaringType.TypeAsTBD, ((IConvertible)args[0]).ToInt64(null));
2004-10-19 17:43:55 +04:00
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
internal class EnumValueFieldWrapper : FieldWrapper
2003-08-21 14:06:34 +04:00
{
2006-11-27 10:39:30 +03:00
private Type underlyingType;
2005-06-01 13:49:30 +04:00
internal EnumValueFieldWrapper(DotNetTypeWrapper tw, TypeWrapper fieldType)
2006-04-05 12:18:58 +04:00
: base(tw, fieldType, "Value", fieldType.SigName, new ExModifiers(Modifiers.Public | Modifiers.Final, false), null)
2004-12-21 13:26:51 +03:00
{
2006-11-27 10:39:30 +03:00
underlyingType = Enum.GetUnderlyingType(tw.type);
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
protected override void EmitGetImpl(CodeEmitter ilgen)
2004-12-21 13:26:51 +03:00
{
2006-11-27 10:39:30 +03:00
// NOTE if the reference on the stack is null, we *want* the NullReferenceException, so we don't use TypeWrapper.EmitUnbox
ilgen.LazyEmitUnbox(underlyingType);
ilgen.LazyEmitLdobj(underlyingType);
2004-12-21 13:26:51 +03:00
}
2005-06-01 13:49:30 +04:00
protected override void EmitSetImpl(CodeEmitter ilgen)
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException();
2004-12-21 13:26:51 +03:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
2006-04-10 13:09:09 +04:00
#if !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal override void SetValue(object obj, object val)
2004-12-21 13:26:51 +03:00
{
2005-06-01 13:49:30 +04:00
// NOTE even though the field is final, JNI reflection can still be used to set its value!
// NOTE the CLI spec says that an enum has exactly one instance field, so we take advantage of that fact.
FieldInfo f = DeclaringType.TypeAsTBD.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)[0];
f.SetValue(obj, val);
2004-12-21 13:26:51 +03:00
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
// this method takes a boxed Enum and returns its value as a boxed primitive
// of the subset of Java primitives (i.e. byte, short, int, long)
internal static object GetEnumPrimitiveValue(object obj)
2003-08-21 14:06:34 +04:00
{
return GetEnumPrimitiveValue(Enum.GetUnderlyingType(obj.GetType()), obj);
}
// this method can be used to convert an enum value or its underlying value to a Java primitive
internal static object GetEnumPrimitiveValue(Type underlyingType, object obj)
{
2005-06-01 13:49:30 +04:00
if(underlyingType == typeof(sbyte) || underlyingType == typeof(byte))
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return unchecked((byte)((IConvertible)obj).ToInt32(null));
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
else if(underlyingType == typeof(short) || underlyingType == typeof(ushort))
{
return unchecked((short)((IConvertible)obj).ToInt32(null));
}
else if(underlyingType == typeof(int))
{
return ((IConvertible)obj).ToInt32(null);
}
else if(underlyingType == typeof(uint))
{
return unchecked((int)((IConvertible)obj).ToUInt32(null));
}
else if(underlyingType == typeof(long))
{
return ((IConvertible)obj).ToInt64(null);
}
else if(underlyingType == typeof(ulong))
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
return unchecked((long)((IConvertible)obj).ToUInt64(null));
2003-08-21 14:06:34 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
throw new InvalidOperationException();
2003-08-21 14:06:34 +04:00
}
}
2006-04-10 13:09:09 +04:00
#if !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
internal override object GetValue(object obj)
{
return GetEnumPrimitiveValue(obj);
}
2006-04-10 13:09:09 +04:00
#endif // !STATIC_COMPILER
2005-06-01 13:49:30 +04:00
}
private class ValueTypeDefaultCtor : MethodWrapper
{
internal ValueTypeDefaultCtor(DotNetTypeWrapper tw)
: base(tw, "<init>", "()V", null, PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Public, MemberFlags.None)
{
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal override void EmitNewobj(CodeEmitter ilgen, MethodAnalyzer ma, int opcodeIndex)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
LocalBuilder local = ilgen.DeclareLocal(DeclaringType.TypeAsTBD);
ilgen.Emit(OpCodes.Ldloc, local);
ilgen.Emit(OpCodes.Box, DeclaringType.TypeAsTBD);
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
#if !STATIC_COMPILER && !FIRST_PASS
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2005-06-01 13:49:30 +04:00
{
if(obj == null)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
obj = Activator.CreateInstance(DeclaringType.TypeAsTBD);
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
return obj;
2003-08-21 14:06:34 +04:00
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
2006-11-20 12:21:38 +03:00
private class FinalizeMethodWrapper : MethodWrapper
{
internal FinalizeMethodWrapper(DotNetTypeWrapper tw)
: base(tw, "finalize", "()V", null, PrimitiveTypeWrapper.VOID, TypeWrapper.EmptyArray, Modifiers.Protected, MemberFlags.None)
{
}
internal override void EmitCall(CodeEmitter ilgen)
2006-11-20 12:21:38 +03:00
{
ilgen.Emit(OpCodes.Pop);
}
internal override void EmitCallvirt(CodeEmitter ilgen)
2006-11-20 12:21:38 +03:00
{
ilgen.Emit(OpCodes.Pop);
}
#if !STATIC_COMPILER && !FIRST_PASS
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2006-11-20 12:21:38 +03:00
{
return null;
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2006-11-20 12:21:38 +03:00
}
private class CloneMethodWrapper : MethodWrapper
{
internal CloneMethodWrapper(DotNetTypeWrapper tw)
: base(tw, "clone", "()Ljava.lang.Object;", null, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, Modifiers.Protected, MemberFlags.None)
{
}
internal override void EmitCall(CodeEmitter ilgen)
2006-11-20 12:21:38 +03:00
{
ilgen.Emit(OpCodes.Dup);
ilgen.Emit(OpCodes.Isinst, ClassLoaderWrapper.LoadClassCritical("java.lang.Cloneable").TypeAsBaseType);
CodeEmitterLabel label1 = ilgen.DefineLabel();
2006-11-20 12:21:38 +03:00
ilgen.Emit(OpCodes.Brtrue_S, label1);
CodeEmitterLabel label2 = ilgen.DefineLabel();
2006-11-20 12:21:38 +03:00
ilgen.Emit(OpCodes.Brfalse_S, label2);
EmitHelper.Throw(ilgen, "java.lang.CloneNotSupportedException");
ilgen.MarkLabel(label2);
EmitHelper.Throw(ilgen, "java.lang.NullPointerException");
ilgen.MarkLabel(label1);
ilgen.Emit(OpCodes.Call, typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
}
internal override void EmitCallvirt(CodeEmitter ilgen)
2006-11-20 12:21:38 +03:00
{
EmitCall(ilgen);
}
#if !STATIC_COMPILER && !FIRST_PASS
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2006-11-20 12:21:38 +03:00
{
return CoreClasses.java.lang.Object.Wrapper.GetMethodWrapper(Name, Signature, false).Invoke(obj, args, nonVirtual, callerID);
2006-11-20 12:21:38 +03:00
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2006-11-20 12:21:38 +03:00
}
2005-06-01 13:49:30 +04:00
protected override void LazyPublishMembers()
{
// special support for enums
if(type.IsEnum)
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
Type underlyingType = Enum.GetUnderlyingType(type);
if(underlyingType == typeof(sbyte))
{
underlyingType = typeof(byte);
}
else if(underlyingType == typeof(ushort))
{
underlyingType = typeof(short);
}
else if(underlyingType == typeof(uint))
{
underlyingType = typeof(int);
}
else if(underlyingType == typeof(ulong))
{
underlyingType = typeof(long);
}
TypeWrapper fieldType = ClassLoaderWrapper.GetWrapperFromType(underlyingType);
FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
ArrayList fieldsList = new ArrayList();
2005-06-01 13:49:30 +04:00
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;
}
2007-12-17 10:43:06 +03:00
object val = EnumValueFieldWrapper.GetEnumPrimitiveValue(underlyingType, fields[i].GetRawConstantValue());
2006-10-10 20:24:48 +04:00
fieldsList.Add(new ConstantFieldWrapper(this, fieldType, name, fieldType.SigName, Modifiers.Public | Modifiers.Static | Modifiers.Final, fields[i], val, MemberFlags.None));
2005-06-01 13:49:30 +04:00
}
}
fieldsList.Add(new EnumValueFieldWrapper(this, fieldType));
SetFields((FieldWrapper[])fieldsList.ToArray(typeof(FieldWrapper)));
SetMethods(new MethodWrapper[] { new EnumWrapMethodWrapper(this, fieldType) });
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
else
2003-08-21 14:06:34 +04:00
{
ArrayList fieldsList = new ArrayList();
2005-06-01 13:49:30 +04:00
FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
for(int i = 0; i < fields.Length; i++)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// 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
2006-04-05 12:18:58 +04:00
fieldsList.Add(CreateFieldWrapperDotNet(AttributeHelper.GetModifiers(fields[i], true).Modifiers, fields[i].Name, fields[i].FieldType, fields[i]));
2005-06-01 13:49:30 +04:00
}
2003-11-17 15:01:50 +03:00
}
SetFields((FieldWrapper[])fieldsList.ToArray(typeof(FieldWrapper)));
Hashtable methodsList = new Hashtable();
2005-06-01 13:49:30 +04:00
// 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);
2005-06-01 13:49:30 +04:00
}
ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
for(int i = 0; i < constructors.Length; i++)
2003-11-17 15:01:50 +03:00
{
2005-01-03 11:26:21 +03:00
string name;
string sig;
2006-12-05 10:52:25 +03:00
TypeWrapper[] args;
TypeWrapper ret;
if(MakeMethodDescriptor(constructors[i], out name, out sig, out args, out ret))
2005-06-01 13:49:30 +04:00
{
MethodWrapper mw = CreateMethodWrapper(name, sig, args, ret, constructors[i], false);
string key = mw.Name + mw.Signature;
if(!methodsList.ContainsKey(key))
2005-06-01 13:49:30 +04:00
{
methodsList.Add(key, mw);
2005-06-01 13:49:30 +04:00
}
}
}
if(type.IsValueType && !methodsList.ContainsKey("<init>()V"))
2005-06-01 13:49:30 +04:00
{
// Value types have an implicit default ctor
methodsList.Add("<init>()V", new ValueTypeDefaultCtor(this));
2005-06-01 13:49:30 +04:00
}
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)
2003-11-17 15:01:50 +03:00
{
2005-06-01 13:49:30 +04:00
// skip, Java cannot deal with static methods on interfaces
}
else
{
string name;
string sig;
2006-12-05 10:52:25 +03:00
TypeWrapper[] args;
TypeWrapper ret;
if(MakeMethodDescriptor(methods[i], out name, out sig, out args, out ret))
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
if(!methods[i].IsStatic && !methods[i].IsPrivate && BaseTypeWrapper != null)
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper baseMethod = BaseTypeWrapper.GetMethodWrapper(name, sig, true);
if(baseMethod != null && baseMethod.IsFinal && !baseMethod.IsStatic && !baseMethod.IsPrivate)
{
continue;
}
2004-11-04 15:50:28 +03:00
}
MethodWrapper mw = CreateMethodWrapper(name, sig, args, ret, methods[i], false);
string key = mw.Name + mw.Signature;
MethodWrapper existing = (MethodWrapper)methodsList[key];
if(existing == null || existing is ByRefMethodWrapper)
{
methodsList[key] = mw;
}
2004-11-04 15:50:28 +03:00
}
else if(methods[i].IsAbstract)
{
this.HasUnsupportedAbstractMethods = true;
}
2003-12-20 01:19:18 +03:00
}
}
// make sure that all the interface methods that we implement are available as public methods,
// otherwise javac won't like the class.
2005-06-01 13:49:30 +04:00
if(!type.IsInterface)
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
Type[] interfaces = type.GetInterfaces();
for(int i = 0; i < interfaces.Length; i++)
2003-12-20 01:19:18 +03:00
{
// 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(IsVisible(interfaces[i]))
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
InterfaceMapping map = type.GetInterfaceMap(interfaces[i]);
for(int j = 0; j < map.InterfaceMethods.Length; j++)
2003-12-20 01:19:18 +03:00
{
if((!map.TargetMethods[j].IsPublic || map.TargetMethods[j].Name != map.InterfaceMethods[j].Name)
&& map.TargetMethods[j].DeclaringType == type)
2003-12-20 01:19:18 +03:00
{
2005-06-01 13:49:30 +04:00
string name;
string sig;
2006-12-05 10:52:25 +03:00
TypeWrapper[] args;
TypeWrapper ret;
if(MakeMethodDescriptor(map.InterfaceMethods[j], out name, out sig, out args, out ret))
2004-11-04 15:50:28 +03:00
{
string key = name + sig;
MethodWrapper existing = (MethodWrapper)methodsList[key];
if(existing == null && BaseTypeWrapper != null)
2004-11-04 15:50:28 +03:00
{
2005-06-01 13:49:30 +04:00
MethodWrapper baseMethod = BaseTypeWrapper.GetMethodWrapper(name, sig, true);
if(baseMethod != null && !baseMethod.IsStatic && baseMethod.IsPublic)
{
continue;
}
2004-11-04 15:50:28 +03:00
}
if(existing == null || existing is ByRefMethodWrapper || existing.IsStatic || !existing.IsPublic)
2005-06-01 13:49:30 +04:00
{
// TODO if existing != null, we need to rename the existing method (but this is complicated because
// it also affects subclasses). This is especially required is the existing method is abstract,
// because otherwise we won't be able to create any subclasses in Java.
methodsList[key] = CreateMethodWrapper(name, sig, args, ret, map.InterfaceMethods[j], true);
2005-06-01 13:49:30 +04:00
}
2005-02-02 18:11:26 +03:00
}
2003-12-20 01:19:18 +03:00
}
}
}
2003-11-17 15:01:50 +03:00
}
2003-08-21 14:06:34 +04:00
}
2004-04-23 18:21:43 +04:00
2005-06-01 13:49:30 +04:00
// 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)
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
// Finish the type, to make sure the methods are populated
this.BaseTypeWrapper.Finish();
TypeWrapper baseTypeWrapper = this.BaseTypeWrapper;
while(baseTypeWrapper != null)
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
foreach(MethodWrapper m in baseTypeWrapper.GetMethods())
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
if(!m.IsStatic && !m.IsFinal && (m.IsPublic || m.IsProtected) && m.Name != "<init>")
2004-04-23 18:21:43 +04:00
{
string key = m.Name + m.Signature;
if(!methodsList.ContainsKey(key))
2005-06-01 13:49:30 +04:00
{
2006-11-20 12:21:38 +03:00
if(m.IsProtected)
{
if(m.Name == "finalize" && m.Signature == "()V")
{
methodsList.Add(key, new FinalizeMethodWrapper(this));
2006-11-20 12:21:38 +03:00
}
else if(m.Name == "clone" && m.Signature == "()Ljava.lang.Object;")
{
methodsList.Add(key, new CloneMethodWrapper(this));
2006-11-20 12:21:38 +03:00
}
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));
2006-11-20 12:21:38 +03:00
}
2005-06-01 13:49:30 +04:00
}
2004-04-23 18:21:43 +04:00
}
}
2005-06-01 13:49:30 +04:00
baseTypeWrapper = baseTypeWrapper.BaseTypeWrapper;
}
}
MethodWrapper[] methodArray = new MethodWrapper[methodsList.Count];
methodsList.Values.CopyTo(methodArray, 0);
SetMethods(methodArray);
2005-06-01 13:49:30 +04:00
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
private class BaseFinalMethodWrapper : MethodWrapper
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
private MethodWrapper m;
2004-08-17 13:05:21 +04:00
2005-06-01 13:49:30 +04:00
internal BaseFinalMethodWrapper(DotNetTypeWrapper tw, MethodWrapper m)
: base(tw, m.Name, m.Signature, m.GetMethod(), m.ReturnType, m.GetParameters(), m.Modifiers | Modifiers.Final, MemberFlags.None)
{
this.m = m;
}
2004-08-17 13:05:21 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal override void EmitCall(CodeEmitter ilgen)
2005-06-01 13:49:30 +04:00
{
// we direct EmitCall to EmitCallvirt, because we always want to end up at the instancehelper method
// (EmitCall would go to our alter ego .NET type and that wouldn't be legal)
m.EmitCallvirt(ilgen);
}
2004-08-17 13:05:21 +04:00
internal override void EmitCallvirt(CodeEmitter ilgen)
2005-06-01 13:49:30 +04:00
{
m.EmitCallvirt(ilgen);
}
2005-12-07 12:06:32 +03:00
#endif
2005-06-01 13:49:30 +04:00
#if !STATIC_COMPILER && !FIRST_PASS
2005-06-01 13:49:30 +04:00
[HideFromJava]
internal override object Invoke(object obj, object[] args, bool nonVirtual, ikvm.@internal.CallerID callerID)
2005-06-01 13:49:30 +04:00
{
return m.Invoke(obj, args, nonVirtual, callerID);
2005-06-01 13:49:30 +04:00
}
#endif // !STATIC_COMPILER && !FIRST_PASS
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
internal static bool IsUnsupportedAbstractMethod(MethodBase mb)
{
if(mb.IsAbstract)
{
MethodInfo mi = (MethodInfo)mb;
if(mi.ReturnType.IsPointer || mi.ReturnType.IsByRef)
{
return true;
}
foreach(ParameterInfo p in mi.GetParameters())
{
if(p.ParameterType.IsByRef || p.ParameterType.IsPointer)
{
return true;
}
}
}
return false;
}
2006-12-05 10:52:25 +03:00
private bool MakeMethodDescriptor(MethodBase mb, out string name, out string sig, out TypeWrapper[] args, out TypeWrapper ret)
2003-08-21 14:06:34 +04:00
{
2007-11-26 12:01:35 +03:00
if(mb.IsGenericMethodDefinition)
2003-08-21 14:06:34 +04:00
{
2005-01-03 11:26:21 +03:00
name = null;
sig = null;
2006-12-05 10:52:25 +03:00
args = null;
ret = null;
2005-01-03 11:26:21 +03:00
return false;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append('(');
ParameterInfo[] parameters = mb.GetParameters();
2006-12-05 10:52:25 +03:00
args = new TypeWrapper[parameters.Length];
2005-06-01 13:49:30 +04:00
for(int i = 0; i < parameters.Length; i++)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
Type type = parameters[i].ParameterType;
if(type.IsPointer)
2004-10-04 23:30:53 +04:00
{
2005-01-03 11:26:21 +03:00
name = null;
sig = null;
2006-12-05 10:52:25 +03:00
args = null;
ret = null;
2005-01-03 11:26:21 +03:00
return false;
2004-10-04 23:30:53 +04:00
}
2005-06-01 13:49:30 +04:00
if(type.IsByRef)
2003-08-26 15:24:17 +04:00
{
2005-06-01 13:49:30 +04:00
if(type.GetElementType().IsPointer)
{
name = null;
sig = null;
2006-12-05 10:52:25 +03:00
args = null;
ret = null;
2005-06-01 13:49:30 +04:00
return false;
}
2006-07-05 12:46:56 +04:00
type = ArrayTypeWrapper.MakeArrayType(type.GetElementType(), 1);
2005-06-01 13:49:30 +04:00
if(mb.IsAbstract)
{
// Since we cannot override methods with byref arguments, we don't report abstract
// methods with byref args.
name = null;
sig = null;
2006-12-05 10:52:25 +03:00
args = null;
ret = null;
2005-06-01 13:49:30 +04:00
return false;
}
2003-08-26 15:24:17 +04:00
}
2005-06-01 13:49:30 +04:00
TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(type);
args[i] = tw;
sb.Append(tw.SigName);
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
sb.Append(')');
if(mb is ConstructorInfo)
2003-08-21 14:06:34 +04:00
{
2006-12-05 10:52:25 +03:00
ret = PrimitiveTypeWrapper.VOID;
2005-06-01 13:49:30 +04:00
if(mb.IsStatic)
{
name = "<clinit>";
}
else
{
name = "<init>";
}
sb.Append(ret.SigName);
sig = sb.ToString();
return true;
2003-08-21 14:06:34 +04:00
}
else
{
2005-06-01 13:49:30 +04:00
Type type = ((MethodInfo)mb).ReturnType;
if(type.IsPointer || type.IsByRef)
{
name = null;
sig = null;
2006-12-05 10:52:25 +03:00
ret = null;
2005-06-01 13:49:30 +04:00
return false;
}
2006-12-05 10:52:25 +03:00
ret = ClassLoaderWrapper.GetWrapperFromType(type);
2005-06-01 13:49:30 +04:00
sb.Append(ret.SigName);
name = mb.Name;
sig = sb.ToString();
return true;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] Interfaces
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
lock(this)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
if(interfaces == null)
2004-08-17 13:05:21 +04:00
{
2005-06-01 13:49:30 +04:00
Type[] interfaceTypes = type.GetInterfaces();
interfaces = new TypeWrapper[interfaceTypes.Length];
2006-08-29 10:28:34 +04:00
for(int i = 0; i < interfaceTypes.Length; i++)
2004-12-02 11:43:05 +03:00
{
2005-06-01 13:49:30 +04:00
if(interfaceTypes[i].DeclaringType != null &&
2005-12-07 12:06:32 +03:00
AttributeHelper.IsHideFromJava(interfaceTypes[i]) &&
2005-06-01 13:49:30 +04:00
interfaceTypes[i].Name == "__Interface")
{
// we have to return the declaring type for ghost interfaces
interfaces[i] = ClassLoaderWrapper.GetWrapperFromType(interfaceTypes[i].DeclaringType);
}
else
{
interfaces[i] = ClassLoaderWrapper.GetWrapperFromType(interfaceTypes[i]);
}
2004-12-02 11:43:05 +03:00
}
2004-08-17 13:05:21 +04:00
}
2005-06-01 13:49:30 +04:00
return interfaces;
2004-08-17 13:05:21 +04:00
}
2003-08-21 14:06:34 +04:00
}
}
2006-06-15 16:29:11 +04:00
private static bool IsAttribute(Type type)
{
2006-06-20 18:31:56 +04:00
if(!type.IsAbstract && type.IsSubclassOf(typeof(Attribute)) && IsVisible(type))
{
//
// Based on the number of constructors and their arguments, we distinguish several types
// of attributes:
// | def ctor | single 1-arg ctor
// -----------------------------------------------------------------
// complex only (i.e. Annotation{N}) | |
// all optional fields/properties | X |
// required "value" | | X
// optional "value" | X | X
// -----------------------------------------------------------------
//
// TODO currently we don't support "complex only" attributes.
//
ConstructorInfo defCtor;
ConstructorInfo singleOneArgCtor;
AttributeAnnotationTypeWrapper.GetConstructors(type, out defCtor, out singleOneArgCtor);
return defCtor != null || singleOneArgCtor != null;
2006-06-20 18:31:56 +04:00
}
return false;
2006-06-15 16:29:11 +04:00
}
2005-06-01 13:49:30 +04:00
private static bool IsDelegate(Type type)
2004-09-05 13:37:58 +04:00
{
2005-06-01 13:49:30 +04:00
// HACK non-public delegates do not get the special treatment (because they are likely to refer to
// non-public types in the arg list and they're not really useful anyway)
// NOTE we don't have to check in what assembly the type lives, because this is a DotNetTypeWrapper,
// we know that it is a different assembly.
if(!type.IsAbstract && type.IsSubclassOf(typeof(MulticastDelegate)) && IsVisible(type))
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
MethodInfo invoke = type.GetMethod("Invoke");
if(invoke != null)
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
foreach(ParameterInfo p in invoke.GetParameters())
2005-02-11 17:46:58 +03:00
{
2005-06-01 13:49:30 +04:00
// TODO at the moment we don't support delegates with pointer or byref parameters
if(p.ParameterType.IsPointer || p.ParameterType.IsByRef)
{
return false;
}
2005-02-11 17:46:58 +03:00
}
2005-06-01 13:49:30 +04:00
return true;
2005-02-11 17:46:58 +03:00
}
}
2005-06-01 13:49:30 +04:00
return false;
2004-09-05 13:37:58 +04:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] InnerClasses
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
lock(this)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if(innerClasses == null)
2003-08-21 14:06:34 +04:00
{
2006-06-15 16:29:11 +04:00
Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
ArrayList list = new ArrayList(nestedTypes.Length);
for(int i = 0; i < nestedTypes.Length; i++)
{
2007-11-26 12:01:35 +03:00
if (!nestedTypes[i].IsGenericTypeDefinition)
2006-06-15 16:29:11 +04:00
{
list.Add(ClassLoaderWrapper.GetWrapperFromType(nestedTypes[i]));
}
}
2005-06-01 13:49:30 +04:00
if(IsDelegate(type))
{
2006-07-26 18:16:52 +04:00
ClassLoaderWrapper classLoader = GetClassLoader();
list.Add(classLoader.RegisterInitiatingLoader(new DelegateInnerClassTypeWrapper(Name + DelegateInterfaceSuffix, type, classLoader)));
2005-06-01 13:49:30 +04:00
}
2006-06-15 16:29:11 +04:00
if(IsAttribute(type))
2004-09-05 13:37:58 +04:00
{
2006-07-26 13:03:44 +04:00
list.Add(GetClassLoader().RegisterInitiatingLoader(new AttributeAnnotationTypeWrapper(Name + AttributeAnnotationSuffix, type)));
2007-01-04 10:46:38 +03:00
}
if(type.IsEnum && IsVisible(type))
{
list.Add(GetClassLoader().RegisterInitiatingLoader(new EnumEnumTypeWrapper(Name + EnumEnumSuffix, type)));
2004-09-05 13:37:58 +04:00
}
2006-06-15 16:29:11 +04:00
innerClasses = (TypeWrapper[])list.ToArray(typeof(TypeWrapper));
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
return innerClasses;
2003-08-21 14:06:34 +04:00
}
}
internal override bool IsFakeTypeContainer
{
get
{
return IsDelegate(type) || IsAttribute(type) || (type.IsEnum && IsVisible(type));
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if(outerClass == null)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
Type outer = type.DeclaringType;
if(outer != null && !type.IsGenericType)
2005-06-01 13:49:30 +04:00
{
outerClass = ClassLoaderWrapper.GetWrapperFromType(outer);
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
return outerClass;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if(DeclaringTypeWrapper != null)
{
return Modifiers | Modifiers.Static;
}
return Modifiers;
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
private FieldWrapper CreateFieldWrapperDotNet(Modifiers modifiers, string name, Type fieldType, FieldInfo field)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
TypeWrapper type = ClassLoaderWrapper.GetWrapperFromType(fieldType);
if(field.IsLiteral)
{
2006-10-10 20:24:48 +04:00
return new ConstantFieldWrapper(this, type, name, type.SigName, modifiers, field, null, MemberFlags.None);
2005-06-01 13:49:30 +04:00
}
else
{
2006-04-05 12:18:58 +04:00
return FieldWrapper.Create(this, type, field, name, type.SigName, new ExModifiers(modifiers, false));
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
}
2006-12-05 10:52:25 +03:00
private MethodWrapper CreateMethodWrapper(string name, string sig, TypeWrapper[] argTypeWrappers, TypeWrapper retTypeWrapper, MethodBase mb, bool privateInterfaceImplHack)
2003-08-21 14:06:34 +04:00
{
2006-04-05 12:18:58 +04:00
ExModifiers exmods = AttributeHelper.GetModifiers(mb, true);
Modifiers mods = exmods.Modifiers;
2005-06-01 13:49:30 +04:00
if(name == "Finalize" && sig == "()V" && !mb.IsStatic &&
TypeAsBaseType.IsSubclassOf(CoreClasses.java.lang.Object.Wrapper.TypeAsBaseType))
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
// TODO if the .NET also has a "finalize" method, we need to hide that one (or rename it, or whatever)
MethodWrapper mw = new SimpleCallMethodWrapper(this, "finalize", "()V", (MethodInfo)mb, null, null, mods, MemberFlags.None, SimpleOpCode.Call, SimpleOpCode.Callvirt);
mw.SetDeclaredExceptions(new string[] { "java.lang.Throwable" });
return mw;
}
ParameterInfo[] parameters = mb.GetParameters();
Type[] args = new Type[parameters.Length];
bool hasByRefArgs = false;
bool[] byrefs = null;
for(int i = 0; i < parameters.Length; i++)
{
args[i] = parameters[i].ParameterType;
if(parameters[i].ParameterType.IsByRef)
2003-08-26 15:24:17 +04:00
{
2005-06-01 13:49:30 +04:00
if(byrefs == null)
{
byrefs = new bool[args.Length];
}
byrefs[i] = true;
hasByRefArgs = true;
2003-08-26 15:24:17 +04:00
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
if(privateInterfaceImplHack)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
mods &= ~Modifiers.Abstract;
2004-08-17 13:05:21 +04:00
mods |= Modifiers.Final;
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
if(hasByRefArgs)
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if(!(mb is ConstructorInfo) && !mb.IsStatic)
{
mods |= Modifiers.Final;
}
2006-12-05 10:52:25 +03:00
return new ByRefMethodWrapper(args, byrefs, this, name, sig, mb, retTypeWrapper, argTypeWrappers, mods, false);
2003-08-21 14:06:34 +04:00
}
2004-08-17 13:05:21 +04:00
else
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
if(mb is ConstructorInfo)
{
2006-12-05 10:52:25 +03:00
return new SmartConstructorMethodWrapper(this, name, sig, (ConstructorInfo)mb, argTypeWrappers, mods, MemberFlags.None);
2005-06-01 13:49:30 +04:00
}
else
{
2006-12-05 10:52:25 +03:00
return new SmartCallMethodWrapper(this, name, sig, (MethodInfo)mb, retTypeWrapper, argTypeWrappers, mods, MemberFlags.None, SimpleOpCode.Call, SimpleOpCode.Callvirt);
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
}
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return type;
}
2003-08-21 14:06:34 +04:00
}
2004-04-23 18:21:43 +04:00
2005-06-01 13:49:30 +04:00
internal override bool IsRemapped
2004-04-23 18:21:43 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
return ClassLoaderWrapper.IsRemappedType(type);
}
2004-04-23 18:21:43 +04:00
}
2004-10-19 17:43:55 +04:00
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
internal override void EmitInstanceOf(TypeWrapper context, CodeEmitter ilgen)
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
if(IsRemapped)
2004-10-19 17:43:55 +04:00
{
2006-05-23 16:49:16 +04:00
TypeWrapper shadow = ClassLoaderWrapper.GetWrapperFromType(type);
2005-06-01 13:49:30 +04:00
MethodInfo method = shadow.TypeAsBaseType.GetMethod("__<instanceof>");
if(method != null)
{
ilgen.Emit(OpCodes.Call, method);
return;
}
2004-10-19 17:43:55 +04:00
}
2006-11-27 10:39:30 +03:00
ilgen.LazyEmit_instanceof(type);
2004-10-19 17:43:55 +04:00
}
internal override void EmitCheckcast(TypeWrapper context, CodeEmitter ilgen)
2004-10-19 17:43:55 +04:00
{
2005-06-01 13:49:30 +04:00
if(IsRemapped)
2004-10-19 17:43:55 +04:00
{
2006-05-23 16:49:16 +04:00
TypeWrapper shadow = ClassLoaderWrapper.GetWrapperFromType(type);
2005-06-01 13:49:30 +04:00
MethodInfo method = shadow.TypeAsBaseType.GetMethod("__<checkcast>");
if(method != null)
{
ilgen.Emit(OpCodes.Call, method);
return;
}
2004-10-19 17:43:55 +04:00
}
2005-06-01 13:49:30 +04:00
EmitHelper.Castclass(ilgen, type);
2004-10-19 17:43:55 +04:00
}
2005-12-07 12:06:32 +03:00
#endif
2005-01-03 11:26:21 +03:00
2005-08-05 12:40:54 +04:00
internal override void Finish()
2005-01-03 11:26:21 +03:00
{
2006-03-01 15:26:25 +03:00
if(BaseTypeWrapper != null)
{
BaseTypeWrapper.Finish();
}
foreach(TypeWrapper tw in this.Interfaces)
{
tw.Finish();
}
2005-01-03 11:26:21 +03:00
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature()
{
return null;
}
internal override string GetGenericMethodSignature(MethodWrapper mw)
{
return null;
}
internal override string GetGenericFieldSignature(FieldWrapper fw)
{
return null;
}
internal override string[] GetEnclosingMethod()
{
return null;
}
2005-11-01 17:01:42 +03:00
internal override object[] GetDeclaredAnnotations()
{
if(type.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
2005-11-01 17:01:42 +03:00
return type.GetCustomAttributes(false);
}
internal override object[] GetFieldAnnotations(FieldWrapper fw)
{
FieldInfo fi = fw.GetField();
if(fi == null)
{
return null;
}
if(fi.DeclaringType.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
return fi.GetCustomAttributes(false);
}
internal override object[] GetMethodAnnotations(MethodWrapper mw)
{
MethodBase mb = mw.GetMethod();
if(mb == null)
{
return null;
}
if(mb.DeclaringType.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
return null;
}
return mb.GetCustomAttributes(false);
}
internal override object[][] GetParameterAnnotations(MethodWrapper mw)
{
MethodBase mb = mw.GetMethod();
if(mb == null)
{
return null;
}
if(mb.DeclaringType.Assembly.ReflectionOnly)
{
// TODO on Whidbey this must be implemented
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;
}
2005-01-03 11:26:21 +03:00
}
2003-08-21 14:06:34 +04:00
2005-06-01 13:49:30 +04:00
sealed class ArrayTypeWrapper : TypeWrapper
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
private static TypeWrapper[] interfaces;
private static MethodInfo clone;
2006-07-27 18:44:51 +04:00
private readonly TypeWrapper ultimateElementTypeWrapper;
private Type arrayType;
2007-08-08 16:50:48 +04:00
private bool finished;
2005-01-03 11:26:21 +03:00
2006-07-27 18:44:51 +04:00
internal ArrayTypeWrapper(TypeWrapper ultimateElementTypeWrapper, string name)
: base(Modifiers.Final | Modifiers.Abstract | (ultimateElementTypeWrapper.Modifiers & Modifiers.Public), name, CoreClasses.java.lang.Object.Wrapper)
2003-08-21 14:06:34 +04:00
{
2006-07-27 18:44:51 +04:00
this.ultimateElementTypeWrapper = ultimateElementTypeWrapper;
2006-10-12 10:44:16 +04:00
this.IsInternal = ultimateElementTypeWrapper.IsInternal;
2006-03-23 14:57:41 +03:00
}
internal override ClassLoaderWrapper GetClassLoader()
{
2006-07-27 18:44:51 +04:00
return ultimateElementTypeWrapper.GetClassLoader();
2003-08-21 14:06:34 +04:00
}
2004-08-17 13:05:21 +04:00
2005-08-05 12:40:54 +04:00
internal static MethodInfo CloneMethod
2004-12-22 11:04:10 +03:00
{
2005-08-05 12:40:54 +04:00
get
2005-06-01 13:49:30 +04:00
{
2005-08-05 12:40:54 +04:00
if(clone == null)
{
clone = typeof(Array).GetMethod("Clone", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
}
return clone;
2005-06-01 13:49:30 +04:00
}
2005-08-05 12:40:54 +04:00
}
protected override void LazyPublishMembers()
{
MethodWrapper mw = new SimpleCallMethodWrapper(this, "clone", "()Ljava.lang.Object;", CloneMethod, CoreClasses.java.lang.Object.Wrapper, TypeWrapper.EmptyArray, Modifiers.Public, MemberFlags.HideFromReflection, SimpleOpCode.Callvirt, SimpleOpCode.Callvirt);
2005-06-01 13:49:30 +04:00
mw.Link();
SetMethods(new MethodWrapper[] { mw });
SetFields(FieldWrapper.EmptyArray);
2004-12-22 11:04:10 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Modifiers ReflectiveModifiers
2003-08-21 14:06:34 +04:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-07-27 18:44:51 +04:00
return Modifiers.Final | Modifiers.Abstract | (ultimateElementTypeWrapper.ReflectiveModifiers & Modifiers.AccessMask);
2005-06-01 13:49:30 +04:00
}
2003-08-21 14:06:34 +04:00
}
2005-06-01 13:49:30 +04:00
internal override string SigName
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
// for arrays the signature name is the same as the normal name
return Name;
2003-02-22 15:28:12 +03:00
}
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper[] Interfaces
{
get
{
if(interfaces == null)
{
TypeWrapper[] tw = new TypeWrapper[2];
tw[0] = ClassLoaderWrapper.LoadClassCritical("java.lang.Cloneable");
tw[1] = ClassLoaderWrapper.LoadClassCritical("java.io.Serializable");
interfaces = tw;
}
return interfaces;
}
}
internal override TypeWrapper[] InnerClasses
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return TypeWrapper.EmptyArray;
}
2003-02-22 15:28:12 +03:00
}
2005-06-01 13:49:30 +04:00
internal override TypeWrapper DeclaringTypeWrapper
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
return null;
}
2003-02-22 15:28:12 +03:00
}
2005-06-01 13:49:30 +04:00
internal override Type TypeAsTBD
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
get
{
2006-07-27 18:44:51 +04:00
if(arrayType == null)
{
arrayType = MakeArrayType(ultimateElementTypeWrapper.TypeAsArrayType, this.ArrayRank);
}
return arrayType;
2005-06-01 13:49:30 +04:00
}
2003-02-22 15:28:12 +03:00
}
2005-08-05 12:40:54 +04:00
internal override void Finish()
2003-02-22 15:28:12 +03:00
{
2005-06-01 13:49:30 +04:00
lock(this)
2003-02-22 15:28:12 +03:00
{
2007-08-08 16:50:48 +04:00
if(!finished)
2005-06-01 13:49:30 +04:00
{
2007-08-08 16:50:48 +04:00
finished = true;
2006-07-27 18:44:51 +04:00
ultimateElementTypeWrapper.Finish();
arrayType = MakeArrayType(ultimateElementTypeWrapper.TypeAsArrayType, this.ArrayRank);
2007-08-08 16:50:48 +04:00
ClassLoaderWrapper.ResetWrapperForType(arrayType, this);
2005-06-01 13:49:30 +04:00
}
2003-02-22 15:28:12 +03:00
}
}
2005-10-01 15:16:11 +04:00
internal override string GetGenericSignature()
{
return null;
}
internal override string GetGenericMethodSignature(MethodWrapper mw)
{
return null;
}
internal override string GetGenericFieldSignature(FieldWrapper fw)
{
return null;
}
internal override string[] GetEnclosingMethod()
{
return null;
}
2006-07-05 12:46:56 +04:00
internal static Type MakeArrayType(Type type, int dims)
{
// NOTE this is not just an optimization, but it is also required to
// make sure that ReflectionOnly types stay ReflectionOnly types
// (in particular instantiations of generic types from mscorlib that
// have ReflectionOnly type parameters).
for(int i = 0; i < dims; i++)
{
type = type.MakeArrayType();
}
return type;
}
2003-02-22 15:28:12 +03:00
}
}