зеркало из https://github.com/mono/ikvm-fork.git
Instead of mangling field names and using NameSigAttribute, we now use modopt to modify the signature and record the real type.
This commit is contained in:
Родитель
917376e242
Коммит
6dce5cc447
|
@ -37,9 +37,6 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
sealed class DynamicClassLoader : TypeWrapperFactory
|
sealed class DynamicClassLoader : TypeWrapperFactory
|
||||||
{
|
{
|
||||||
// note that MangleNestedTypeName() assumes that there are less than 16 special characters
|
|
||||||
private static readonly char[] specialCharacters = { '\\', '+', ',', '[', ']', '*', '&', '\u0000' };
|
|
||||||
private static readonly string specialCharactersString = new String(specialCharacters);
|
|
||||||
#if !STATIC_COMPILER
|
#if !STATIC_COMPILER
|
||||||
private static List<AssemblyBuilder> saveDebugAssemblies;
|
private static List<AssemblyBuilder> saveDebugAssemblies;
|
||||||
private static List<DynamicClassLoader> saveClassLoaders;
|
private static List<DynamicClassLoader> saveClassLoaders;
|
||||||
|
@ -137,36 +134,6 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
#endif // !STATIC_COMPILER
|
#endif // !STATIC_COMPILER
|
||||||
|
|
||||||
internal static string EscapeName(string name)
|
|
||||||
{
|
|
||||||
// TODO the escaping of special characters is not required on .NET 2.0
|
|
||||||
// (but it doesn't really hurt that much either, the only overhead is the
|
|
||||||
// extra InnerClassAttribute to record the real name of the class)
|
|
||||||
// Note that even though .NET 2.0 automatically escapes the special characters,
|
|
||||||
// the name that gets passed in ResolveEventArgs.Name of the TypeResolve event
|
|
||||||
// contains the unescaped type name.
|
|
||||||
if(name.IndexOfAny(specialCharacters) >= 0)
|
|
||||||
{
|
|
||||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
||||||
foreach(char c in name)
|
|
||||||
{
|
|
||||||
if(specialCharactersString.IndexOf(c) >= 0)
|
|
||||||
{
|
|
||||||
if(c == 0)
|
|
||||||
{
|
|
||||||
// we can't escape the NUL character, so we replace it with a space.
|
|
||||||
sb.Append(' ');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sb.Append('\\');
|
|
||||||
}
|
|
||||||
sb.Append(c);
|
|
||||||
}
|
|
||||||
name = sb.ToString();
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override bool ReserveName(string name)
|
internal override bool ReserveName(string name)
|
||||||
{
|
{
|
||||||
lock(dynamicTypes)
|
lock(dynamicTypes)
|
||||||
|
@ -184,7 +151,7 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
lock(dynamicTypes)
|
lock(dynamicTypes)
|
||||||
{
|
{
|
||||||
mangledTypeName = EscapeName(mangledTypeName);
|
mangledTypeName = TypeNameUtil.EscapeName(mangledTypeName);
|
||||||
// FXBUG the CLR (both 1.1 and 2.0) doesn't like type names that end with a single period,
|
// FXBUG the CLR (both 1.1 and 2.0) doesn't like type names that end with a single period,
|
||||||
// it loses the trailing period in the name that gets passed in the TypeResolve event.
|
// it loses the trailing period in the name that gets passed in the TypeResolve event.
|
||||||
if(dynamicTypes.ContainsKey(mangledTypeName) || mangledTypeName.EndsWith("."))
|
if(dynamicTypes.ContainsKey(mangledTypeName) || mangledTypeName.EndsWith("."))
|
||||||
|
@ -268,7 +235,7 @@ namespace IKVM.Internal
|
||||||
AttributeHelper.SetEditorBrowsableNever(proxyHelperContainer);
|
AttributeHelper.SetEditorBrowsableNever(proxyHelperContainer);
|
||||||
proxyHelpers = new List<TypeBuilder>();
|
proxyHelpers = new List<TypeBuilder>();
|
||||||
}
|
}
|
||||||
proxyHelpers.Add(proxyHelperContainer.DefineNestedType(MangleNestedTypeName(type.FullName), TypeAttributes.NestedPublic | TypeAttributes.Interface | TypeAttributes.Abstract, null, new Type[] { type }));
|
proxyHelpers.Add(proxyHelperContainer.DefineNestedType(TypeNameUtil.MangleNestedTypeName(type.FullName), TypeAttributes.NestedPublic | TypeAttributes.Interface | TypeAttributes.Abstract, null, new Type[] { type }));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal TypeBuilder DefineProxy(TypeWrapper proxyClass, TypeWrapper[] interfaces)
|
internal TypeBuilder DefineProxy(TypeWrapper proxyClass, TypeWrapper[] interfaces)
|
||||||
|
@ -298,7 +265,7 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
sb.Append(tw.Name.Length).Append('|').Append(tw.Name);
|
sb.Append(tw.Name.Length).Append('|').Append(tw.Name);
|
||||||
}
|
}
|
||||||
return MangleNestedTypeName(sb.ToString());
|
return TypeNameUtil.MangleNestedTypeName(sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetProxyName(TypeWrapper[] interfaces)
|
internal static string GetProxyName(TypeWrapper[] interfaces)
|
||||||
|
@ -308,37 +275,7 @@ namespace IKVM.Internal
|
||||||
|
|
||||||
internal static string GetProxyHelperName(Type type)
|
internal static string GetProxyHelperName(Type type)
|
||||||
{
|
{
|
||||||
return "__<Proxy>+" + MangleNestedTypeName(type.FullName);
|
return "__<Proxy>+" + TypeNameUtil.MangleNestedTypeName(type.FullName);
|
||||||
}
|
|
||||||
|
|
||||||
private static string MangleNestedTypeName(string name)
|
|
||||||
{
|
|
||||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
||||||
foreach (char c in name)
|
|
||||||
{
|
|
||||||
int index = specialCharactersString.IndexOf(c);
|
|
||||||
if(c == '.')
|
|
||||||
{
|
|
||||||
sb.Append("_");
|
|
||||||
}
|
|
||||||
else if(c == '_')
|
|
||||||
{
|
|
||||||
sb.Append("^-");
|
|
||||||
}
|
|
||||||
else if(index == -1)
|
|
||||||
{
|
|
||||||
sb.Append(c);
|
|
||||||
if(c == '^')
|
|
||||||
{
|
|
||||||
sb.Append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.Append('^').AppendFormat("{0:X1}", index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override Type DefineUnloadable(string name)
|
internal override Type DefineUnloadable(string name)
|
||||||
|
@ -359,7 +296,7 @@ namespace IKVM.Internal
|
||||||
unloadableContainer = moduleBuilder.DefineType("__<Unloadable>", TypeAttributes.Interface | TypeAttributes.Abstract);
|
unloadableContainer = moduleBuilder.DefineType("__<Unloadable>", TypeAttributes.Interface | TypeAttributes.Abstract);
|
||||||
AttributeHelper.HideFromJava(unloadableContainer);
|
AttributeHelper.HideFromJava(unloadableContainer);
|
||||||
}
|
}
|
||||||
type = unloadableContainer.DefineNestedType(MangleNestedTypeName(name), TypeAttributes.NestedPrivate | TypeAttributes.Interface | TypeAttributes.Abstract);
|
type = unloadableContainer.DefineNestedType(TypeNameUtil.MangleNestedTypeName(name), TypeAttributes.NestedPrivate | TypeAttributes.Interface | TypeAttributes.Abstract);
|
||||||
unloadables.Add(name, type);
|
unloadables.Add(name, type);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1138,7 +1138,7 @@ namespace IKVM.Internal
|
||||||
private static string GetInnerClassName(string outer, string inner)
|
private static string GetInnerClassName(string outer, string inner)
|
||||||
{
|
{
|
||||||
Debug.Assert(CheckInnerOuterNames(inner, outer));
|
Debug.Assert(CheckInnerOuterNames(inner, outer));
|
||||||
return DynamicClassLoader.EscapeName(inner.Substring(outer.Length + 1));
|
return TypeNameUtil.EscapeName(inner.Substring(outer.Length + 1));
|
||||||
}
|
}
|
||||||
#endif // STATIC_COMPILER
|
#endif // STATIC_COMPILER
|
||||||
|
|
||||||
|
@ -1279,24 +1279,12 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
fieldAttribs |= FieldAttributes.InitOnly;
|
fieldAttribs |= FieldAttributes.InitOnly;
|
||||||
}
|
}
|
||||||
return typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType, fieldAttribs);
|
return DefineField(fw.Name, fw.FieldTypeWrapper, fieldAttribs, fw.IsVolatile);
|
||||||
}
|
}
|
||||||
#endif // STATIC_COMPILER
|
#endif // STATIC_COMPILER
|
||||||
FieldBuilder field;
|
FieldBuilder field;
|
||||||
ClassFile.Field fld = classFile.Fields[fieldIndex];
|
ClassFile.Field fld = classFile.Fields[fieldIndex];
|
||||||
string fieldName = fld.Name;
|
string realFieldName = fld.Name;
|
||||||
TypeWrapper typeWrapper = fw.FieldTypeWrapper;
|
|
||||||
Type type = typeWrapper.TypeAsSignatureType;
|
|
||||||
bool setNameSig = typeWrapper.IsErasedOrBoxedPrimitiveOrRemapped;
|
|
||||||
if (setNameSig)
|
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
string realFieldName = fieldName;
|
|
||||||
FieldAttributes attribs = 0;
|
FieldAttributes attribs = 0;
|
||||||
MethodAttributes methodAttribs = MethodAttributes.HideBySig;
|
MethodAttributes methodAttribs = MethodAttributes.HideBySig;
|
||||||
#if STATIC_COMPILER
|
#if STATIC_COMPILER
|
||||||
|
@ -1336,7 +1324,7 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
Profiler.Count("Static Final Constant");
|
Profiler.Count("Static Final Constant");
|
||||||
attribs |= FieldAttributes.Literal;
|
attribs |= FieldAttributes.Literal;
|
||||||
field = typeBuilder.DefineField(fieldName, type, attribs);
|
field = DefineField(fld.Name, fw.FieldTypeWrapper, attribs, false);
|
||||||
field.SetConstant(constantValue);
|
field.SetConstant(constantValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1378,16 +1366,11 @@ namespace IKVM.Internal
|
||||||
// see https://sourceforge.net/tracker/?func=detail&atid=525264&aid=3056721&group_id=69637
|
// see https://sourceforge.net/tracker/?func=detail&atid=525264&aid=3056721&group_id=69637
|
||||||
// additional note: now that we maintain the ordering of the fields, we need to recognize
|
// additional note: now that we maintain the ordering of the fields, we need to recognize
|
||||||
// these fields so that we know where to insert the corresponding accessor property FieldWrapper.
|
// these fields so that we know where to insert the corresponding accessor property FieldWrapper.
|
||||||
realFieldName = NamePrefix.Type2AccessStubBackingField + fieldName;
|
realFieldName = NamePrefix.Type2AccessStubBackingField + fld.Name;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Type[] modreq = Type.EmptyTypes;
|
field = DefineField(realFieldName, fw.FieldTypeWrapper, attribs, fld.IsVolatile);
|
||||||
if (fld.IsVolatile)
|
|
||||||
{
|
|
||||||
modreq = new Type[] { Types.IsVolatile };
|
|
||||||
}
|
|
||||||
field = typeBuilder.DefineField(realFieldName, type, modreq, Type.EmptyTypes, attribs);
|
|
||||||
if (fld.IsTransient)
|
if (fld.IsTransient)
|
||||||
{
|
{
|
||||||
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(JVM.Import(typeof(NonSerializedAttribute)).GetConstructor(Type.EmptyTypes), new object[0]);
|
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(JVM.Import(typeof(NonSerializedAttribute)).GetConstructor(Type.EmptyTypes), new object[0]);
|
||||||
|
@ -1396,7 +1379,7 @@ namespace IKVM.Internal
|
||||||
if (isWrappedFinal)
|
if (isWrappedFinal)
|
||||||
{
|
{
|
||||||
methodAttribs |= MethodAttributes.SpecialName;
|
methodAttribs |= MethodAttributes.SpecialName;
|
||||||
MethodBuilder getter = typeBuilder.DefineMethod(GenerateUniqueMethodName("get_" + fieldName, type, Type.EmptyTypes), methodAttribs, CallingConventions.Standard, type, Type.EmptyTypes);
|
MethodBuilder getter = typeBuilder.DefineMethod(GenerateUniqueMethodName("get_" + fld.Name, fw.FieldTypeWrapper.TypeAsSignatureType, Type.EmptyTypes), methodAttribs, CallingConventions.Standard, fw.FieldTypeWrapper.TypeAsSignatureType, Type.EmptyTypes);
|
||||||
AttributeHelper.HideFromJava(getter);
|
AttributeHelper.HideFromJava(getter);
|
||||||
CodeEmitter ilgen = CodeEmitter.Create(getter);
|
CodeEmitter ilgen = CodeEmitter.Create(getter);
|
||||||
if (fld.IsStatic)
|
if (fld.IsStatic)
|
||||||
|
@ -1411,13 +1394,13 @@ namespace IKVM.Internal
|
||||||
ilgen.Emit(OpCodes.Ret);
|
ilgen.Emit(OpCodes.Ret);
|
||||||
ilgen.DoEmit();
|
ilgen.DoEmit();
|
||||||
|
|
||||||
PropertyBuilder pb = typeBuilder.DefineProperty(fieldName, PropertyAttributes.None, type, Type.EmptyTypes);
|
PropertyBuilder pb = typeBuilder.DefineProperty(fld.Name, PropertyAttributes.None, fw.FieldTypeWrapper.TypeAsSignatureType, Type.EmptyTypes);
|
||||||
pb.SetGetMethod(getter);
|
pb.SetGetMethod(getter);
|
||||||
if (!fld.IsStatic)
|
if (!fld.IsStatic)
|
||||||
{
|
{
|
||||||
// this method exist for use by reflection only
|
// 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)
|
// (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, Types.Void, new Type[] { type });
|
MethodBuilder setter = typeBuilder.DefineMethod("__<set>", MethodAttributes.PrivateScope, CallingConventions.Standard, Types.Void, new Type[] { fw.FieldTypeWrapper.TypeAsSignatureType });
|
||||||
ilgen = CodeEmitter.Create(setter);
|
ilgen = CodeEmitter.Create(setter);
|
||||||
ilgen.Emit(OpCodes.Ldarg_0);
|
ilgen.Emit(OpCodes.Ldarg_0);
|
||||||
ilgen.Emit(OpCodes.Ldarg_1);
|
ilgen.Emit(OpCodes.Ldarg_1);
|
||||||
|
@ -1428,7 +1411,7 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
((GetterFieldWrapper)fw).SetGetter(getter);
|
((GetterFieldWrapper)fw).SetGetter(getter);
|
||||||
#if STATIC_COMPILER
|
#if STATIC_COMPILER
|
||||||
if (setNameSig)
|
if (fw.FieldTypeWrapper.IsErasedOrBoxedPrimitiveOrRemapped)
|
||||||
{
|
{
|
||||||
AttributeHelper.SetNameSig(getter, fld.Name, fld.Signature);
|
AttributeHelper.SetNameSig(getter, fld.Name, fld.Signature);
|
||||||
}
|
}
|
||||||
|
@ -1457,10 +1440,6 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
AttributeHelper.SetModifiers(field, fld.Modifiers, fld.IsInternal);
|
AttributeHelper.SetModifiers(field, fld.Modifiers, fld.IsInternal);
|
||||||
}
|
}
|
||||||
if (setNameSig)
|
|
||||||
{
|
|
||||||
AttributeHelper.SetNameSig(field, fld.Name, fld.Signature);
|
|
||||||
}
|
|
||||||
if (fld.DeprecatedAttribute)
|
if (fld.DeprecatedAttribute)
|
||||||
{
|
{
|
||||||
AttributeHelper.SetDeprecatedAttribute(field);
|
AttributeHelper.SetDeprecatedAttribute(field);
|
||||||
|
@ -1474,6 +1453,58 @@ namespace IKVM.Internal
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FieldBuilder DefineField(string name, TypeWrapper tw, FieldAttributes attribs, bool isVolatile)
|
||||||
|
{
|
||||||
|
Type[] modreq = isVolatile ? new Type[] { Types.IsVolatile } : Type.EmptyTypes;
|
||||||
|
return typeBuilder.DefineField(name, tw.TypeAsSignatureType, modreq, GetModOpt(tw), attribs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type[] GetModOpt(TypeWrapper tw)
|
||||||
|
{
|
||||||
|
Type[] modopt = Type.EmptyTypes;
|
||||||
|
if (tw.IsUnloadable)
|
||||||
|
{
|
||||||
|
modopt = new Type[] { wrapper.GetClassLoader().GetTypeWrapperFactory().DefineUnloadable(tw.Name) };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TypeWrapper tw1 = tw.IsArray ? tw.GetUltimateElementTypeWrapper() : tw;
|
||||||
|
if (tw1.IsErasedOrBoxedPrimitiveOrRemapped)
|
||||||
|
{
|
||||||
|
#if STATIC_COMPILER
|
||||||
|
modopt = new Type[] { GetModOptHelper(tw) };
|
||||||
|
#else
|
||||||
|
// FXBUG Ref.Emit refuses arrays in custom modifiers, so we add an array type for each dimension
|
||||||
|
// (note that in this case we only add the custom modifiers to make the signature unique, we never read back this information)
|
||||||
|
modopt = new Type[tw.ArrayRank + 1];
|
||||||
|
modopt[0] = GetModOptHelper(tw1);
|
||||||
|
for (int i = 1; i < modopt.Length; i++)
|
||||||
|
{
|
||||||
|
modopt[i] = typeof(Array);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Type GetModOptHelper(TypeWrapper tw)
|
||||||
|
{
|
||||||
|
Debug.Assert(!tw.IsUnloadable);
|
||||||
|
if (tw.IsArray)
|
||||||
|
{
|
||||||
|
return ArrayTypeWrapper.MakeArrayType(GetModOptHelper(tw.GetUltimateElementTypeWrapper()), tw.ArrayRank);
|
||||||
|
}
|
||||||
|
else if (tw.IsGhost)
|
||||||
|
{
|
||||||
|
return tw.TypeAsTBD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return tw.TypeAsBaseType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
|
internal override void EmitRunClassConstructor(CodeEmitter ilgen)
|
||||||
{
|
{
|
||||||
if (clinitMethod != null)
|
if (clinitMethod != null)
|
||||||
|
|
|
@ -812,12 +812,6 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetNameSig(FieldBuilder fb, string name, string sig)
|
|
||||||
{
|
|
||||||
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeofNameSigAttribute.GetConstructor(new Type[] { Types.String, Types.String }), new object[] { name, sig });
|
|
||||||
fb.SetCustomAttribute(customAttributeBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void SetNameSig(PropertyBuilder pb, string name, string sig)
|
internal static void SetNameSig(PropertyBuilder pb, string name, string sig)
|
||||||
{
|
{
|
||||||
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeofNameSigAttribute.GetConstructor(new Type[] { Types.String, Types.String }), new object[] { name, sig });
|
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeofNameSigAttribute.GetConstructor(new Type[] { Types.String, Types.String }), new object[] { name, sig });
|
||||||
|
@ -1363,6 +1357,108 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class TypeNameUtil
|
||||||
|
{
|
||||||
|
// note that MangleNestedTypeName() assumes that there are less than 16 special characters
|
||||||
|
private static readonly char[] specialCharacters = { '\\', '+', ',', '[', ']', '*', '&', '\u0000' };
|
||||||
|
private static readonly string specialCharactersString = new String(specialCharacters);
|
||||||
|
|
||||||
|
internal static string EscapeName(string name)
|
||||||
|
{
|
||||||
|
// TODO the escaping of special characters is not required on .NET 2.0
|
||||||
|
// (but it doesn't really hurt that much either, the only overhead is the
|
||||||
|
// extra InnerClassAttribute to record the real name of the class)
|
||||||
|
// Note that even though .NET 2.0 automatically escapes the special characters,
|
||||||
|
// the name that gets passed in ResolveEventArgs.Name of the TypeResolve event
|
||||||
|
// contains the unescaped type name.
|
||||||
|
if (name.IndexOfAny(specialCharacters) >= 0)
|
||||||
|
{
|
||||||
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||||
|
foreach (char c in name)
|
||||||
|
{
|
||||||
|
if (specialCharactersString.IndexOf(c) >= 0)
|
||||||
|
{
|
||||||
|
if (c == 0)
|
||||||
|
{
|
||||||
|
// we can't escape the NUL character, so we replace it with a space.
|
||||||
|
sb.Append(' ');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sb.Append('\\');
|
||||||
|
}
|
||||||
|
sb.Append(c);
|
||||||
|
}
|
||||||
|
name = sb.ToString();
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string MangleNestedTypeName(string name)
|
||||||
|
{
|
||||||
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||||
|
foreach (char c in name)
|
||||||
|
{
|
||||||
|
int index = specialCharactersString.IndexOf(c);
|
||||||
|
if (c == '.')
|
||||||
|
{
|
||||||
|
sb.Append("_");
|
||||||
|
}
|
||||||
|
else if (c == '_')
|
||||||
|
{
|
||||||
|
sb.Append("^-");
|
||||||
|
}
|
||||||
|
else if (index == -1)
|
||||||
|
{
|
||||||
|
sb.Append(c);
|
||||||
|
if (c == '^')
|
||||||
|
{
|
||||||
|
sb.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append('^').AppendFormat("{0:X1}", index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string UnmangleNestedTypeName(string name)
|
||||||
|
{
|
||||||
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||||
|
for (int i = 0; i < name.Length; i++)
|
||||||
|
{
|
||||||
|
char c = name[i];
|
||||||
|
int index = specialCharactersString.IndexOf(c);
|
||||||
|
if (c == '_')
|
||||||
|
{
|
||||||
|
sb.Append('.');
|
||||||
|
}
|
||||||
|
else if (c == '^')
|
||||||
|
{
|
||||||
|
c = name[++i];
|
||||||
|
if (c == '-')
|
||||||
|
{
|
||||||
|
sb.Append('_');
|
||||||
|
}
|
||||||
|
else if (c == '^')
|
||||||
|
{
|
||||||
|
sb.Append('^');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(specialCharactersString[c - '0']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abstract class Annotation
|
abstract class Annotation
|
||||||
{
|
{
|
||||||
// NOTE this method returns null if the type could not be found
|
// NOTE this method returns null if the type could not be found
|
||||||
|
@ -2129,6 +2225,11 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal virtual TypeWrapper GetUltimateElementTypeWrapper()
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
internal bool IsNonPrimitiveValueType
|
internal bool IsNonPrimitiveValueType
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -4272,17 +4373,36 @@ namespace IKVM.Internal
|
||||||
return new GetterFieldWrapper(this, type, null, name, type.SigName, modifiers, getter, prop);
|
return new GetterFieldWrapper(this, type, null, name, type.SigName, modifiers, getter, prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static TypeWrapper TypeWrapperFromModOpt(Type modopt)
|
||||||
|
{
|
||||||
|
int rank = 0;
|
||||||
|
while (ReflectUtil.IsVector(modopt))
|
||||||
|
{
|
||||||
|
rank++;
|
||||||
|
modopt = modopt.GetElementType();
|
||||||
|
}
|
||||||
|
if (rank != 0)
|
||||||
|
{
|
||||||
|
return TypeWrapperFromModOpt(modopt).MakeArrayType(rank);
|
||||||
|
}
|
||||||
|
else if (modopt == Types.Void || modopt.IsPrimitive || ClassLoaderWrapper.IsRemappedType(modopt))
|
||||||
|
{
|
||||||
|
return DotNetTypeWrapper.GetWrapperFromDotNetType(modopt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ClassLoaderWrapper.GetWrapperFromType(modopt)
|
||||||
|
?? new UnloadableTypeWrapper(TypeNameUtil.UnmangleNestedTypeName(modopt.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private FieldWrapper CreateFieldWrapper(FieldInfo field)
|
private FieldWrapper CreateFieldWrapper(FieldInfo field)
|
||||||
{
|
{
|
||||||
ExModifiers modifiers = AttributeHelper.GetModifiers(field, false);
|
ExModifiers modifiers = AttributeHelper.GetModifiers(field, false);
|
||||||
string name = field.Name;
|
Type[] modopt = field.GetOptionalCustomModifiers();
|
||||||
TypeWrapper type = ClassLoaderWrapper.GetWrapperFromType(field.FieldType);
|
TypeWrapper type = modopt.Length == 0
|
||||||
NameSigAttribute attr = AttributeHelper.GetNameSig(field);
|
? ClassLoaderWrapper.GetWrapperFromType(field.FieldType)
|
||||||
if(attr != null)
|
: TypeWrapperFromModOpt(modopt[0]);
|
||||||
{
|
|
||||||
name = attr.Name;
|
|
||||||
SigTypePatchUp(attr.Sig, ref type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(field.IsLiteral)
|
if(field.IsLiteral)
|
||||||
{
|
{
|
||||||
|
@ -4295,11 +4415,11 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
flags |= MemberFlags.InternalAccess;
|
flags |= MemberFlags.InternalAccess;
|
||||||
}
|
}
|
||||||
return new ConstantFieldWrapper(this, type, name, type.SigName, modifiers.Modifiers, field, null, flags);
|
return new ConstantFieldWrapper(this, type, field.Name, type.SigName, modifiers.Modifiers, field, null, flags);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return FieldWrapper.Create(this, type, field, name, type.SigName, modifiers);
|
return FieldWrapper.Create(this, type, field, field.Name, type.SigName, modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4735,6 +4855,11 @@ namespace IKVM.Internal
|
||||||
get { return ultimateElementTypeWrapper.IsFastClassLiteralSafe || ultimateElementTypeWrapper.IsPrimitive; }
|
get { return ultimateElementTypeWrapper.IsFastClassLiteralSafe || ultimateElementTypeWrapper.IsPrimitive; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal override TypeWrapper GetUltimateElementTypeWrapper()
|
||||||
|
{
|
||||||
|
return ultimateElementTypeWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
internal static Type MakeArrayType(Type type, int dims)
|
internal static Type MakeArrayType(Type type, int dims)
|
||||||
{
|
{
|
||||||
// NOTE this is not just an optimization, but it is also required to
|
// NOTE this is not just an optimization, but it is also required to
|
||||||
|
|
Загрузка…
Ссылка в новой задаче