зеркало из https://github.com/mono/ikvm-fork.git
- Fixed IsPackageAccessibleFrom to consider class loaders, instead of InternalsVisibleToAttribute
- Added automatic access to internal accessibility members across assemblies in multi target compilation (previously this was only done for -sharedclassloader scenarios) - Cleaned up existing field access stubs (now known as "type 1") and added type 2 access stubs to make public fields that have a non-public field type accessible.
This commit is contained in:
Родитель
c8dd69be99
Коммит
c7ae133d38
|
@ -432,6 +432,26 @@ namespace IKVM.Internal
|
|||
return null;
|
||||
}
|
||||
|
||||
// HACK when we're compiling multiple targets with -sharedclassloader, each target will have its own CompilerClassLoader,
|
||||
// so we need to consider them equivalent (because they represent the same class loader).
|
||||
internal bool IsEquivalentTo(ClassLoaderWrapper other)
|
||||
{
|
||||
if (this == other)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
CompilerClassLoader ccl = other as CompilerClassLoader;
|
||||
if (ccl != null && options.sharedclassloader != null && options.sharedclassloader.Contains(ccl))
|
||||
{
|
||||
if (!internalsVisibleTo.Contains(ccl))
|
||||
{
|
||||
AddInternalsVisibleToAttribute(ccl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend)
|
||||
{
|
||||
Debug.Assert(wrapper.GetClassLoader() == this);
|
||||
|
@ -442,19 +462,18 @@ namespace IKVM.Internal
|
|||
return true;
|
||||
}
|
||||
CompilerClassLoader ccl = other as CompilerClassLoader;
|
||||
if (ccl != null
|
||||
&& options.sharedclassloader != null
|
||||
&& options.sharedclassloader.Contains(ccl))
|
||||
if (ccl != null)
|
||||
{
|
||||
AddInternalsVisibleToAttribute(ccl.assemblyBuilder);
|
||||
internalsVisibleTo.Add(other);
|
||||
AddInternalsVisibleToAttribute(ccl);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AddInternalsVisibleToAttribute(AssemblyBuilder asm)
|
||||
private void AddInternalsVisibleToAttribute(CompilerClassLoader ccl)
|
||||
{
|
||||
internalsVisibleTo.Add(ccl);
|
||||
AssemblyBuilder asm = ccl.assemblyBuilder;
|
||||
AssemblyName asmName = asm.GetName();
|
||||
string name = asmName.Name;
|
||||
byte[] pubkey = asmName.GetPublicKey();
|
||||
|
|
|
@ -547,12 +547,6 @@ namespace IKVM.Internal
|
|||
}
|
||||
}
|
||||
#if STATIC_COMPILER
|
||||
if (wrapper.IsPublic)
|
||||
{
|
||||
List<FieldWrapper> fieldsArray = new List<FieldWrapper>(fields);
|
||||
AddAccessStubFields(fieldsArray, wrapper);
|
||||
fields = fieldsArray.ToArray();
|
||||
}
|
||||
((AotTypeWrapper)wrapper).AddMapXmlFields(ref fields);
|
||||
#endif
|
||||
wrapper.SetFields(fields);
|
||||
|
@ -1129,29 +1123,6 @@ namespace IKVM.Internal
|
|||
}
|
||||
}
|
||||
|
||||
private void AddAccessStubFields(List<FieldWrapper> 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);
|
||||
}
|
||||
|
||||
private static bool CheckInnerOuterNames(string inner, string outer)
|
||||
{
|
||||
// do some sanity checks on the inner/outer class names
|
||||
|
@ -1252,11 +1223,6 @@ namespace IKVM.Internal
|
|||
|
||||
internal override FieldInfo LinkField(FieldWrapper fw)
|
||||
{
|
||||
if (fw.IsAccessStub)
|
||||
{
|
||||
((AotAccessStubFieldWrapper)fw).DoLink(typeBuilder);
|
||||
return null;
|
||||
}
|
||||
if (fw is DynamicPropertyFieldWrapper)
|
||||
{
|
||||
((DynamicPropertyFieldWrapper)fw).DoLink(typeBuilder);
|
||||
|
@ -1313,6 +1279,7 @@ namespace IKVM.Internal
|
|||
MethodAttributes methodAttribs = MethodAttributes.HideBySig;
|
||||
#if STATIC_COMPILER
|
||||
bool setModifiers = fld.IsInternal || (fld.Modifiers & (Modifiers.Synthetic | Modifiers.Enum)) != 0;
|
||||
bool hideFromJava = false;
|
||||
#endif
|
||||
bool isWrappedFinal = false;
|
||||
if (fld.IsPrivate)
|
||||
|
@ -1334,6 +1301,17 @@ namespace IKVM.Internal
|
|||
attribs |= FieldAttributes.Assembly;
|
||||
methodAttribs |= MethodAttributes.Assembly;
|
||||
}
|
||||
|
||||
#if STATIC_COMPILER
|
||||
if (wrapper.IsPublic && (fw.IsPublic || fw.IsProtected) && !fw.FieldTypeWrapper.IsPublic)
|
||||
{
|
||||
// this field is going to get a type 2 access stub, so we hide the actual field
|
||||
attribs &= ~FieldAttributes.FieldAccessMask;
|
||||
attribs |= FieldAttributes.Assembly;
|
||||
hideFromJava = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fld.IsStatic)
|
||||
{
|
||||
attribs |= FieldAttributes.Static;
|
||||
|
@ -1391,6 +1369,10 @@ namespace IKVM.Internal
|
|||
{
|
||||
AttributeHelper.SetConstantValue(field, constantValue);
|
||||
}
|
||||
if (hideFromJava)
|
||||
{
|
||||
AttributeHelper.HideFromJava(field);
|
||||
}
|
||||
#endif // STATIC_COMPILER
|
||||
if (isWrappedFinal)
|
||||
{
|
||||
|
@ -1511,30 +1493,12 @@ namespace IKVM.Internal
|
|||
classFile.Link(wrapper);
|
||||
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
|
||||
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
|
||||
// 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)
|
||||
|
@ -3911,6 +3875,13 @@ namespace IKVM.Internal
|
|||
|
||||
// See if there is any additional metadata
|
||||
wrapper.EmitMapXmlMetadata(typeBuilder, classFile, fields, methods);
|
||||
|
||||
// if we have public fields that have non-public field types, we need access stubs
|
||||
if (wrapper.IsPublic)
|
||||
{
|
||||
AddType1FieldAccessStubs(wrapper);
|
||||
AddType2FieldAccessStubs();
|
||||
}
|
||||
#endif // STATIC_COMPILER
|
||||
|
||||
for (int i = 0; i < classFile.Methods.Length; i++)
|
||||
|
@ -4083,6 +4054,118 @@ namespace IKVM.Internal
|
|||
return type;
|
||||
}
|
||||
|
||||
#if STATIC_COMPILER
|
||||
private void AddType1FieldAccessStubs(TypeWrapper tw)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!tw.IsPublic)
|
||||
{
|
||||
foreach (FieldWrapper fw in tw.GetFields())
|
||||
{
|
||||
if ((fw.IsPublic || fw.IsProtected)
|
||||
&& wrapper.GetFieldWrapper(fw.Name, fw.Signature) == fw)
|
||||
{
|
||||
GenerateAccessStub(fw, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (TypeWrapper iface in tw.Interfaces)
|
||||
{
|
||||
AddType1FieldAccessStubs(iface);
|
||||
}
|
||||
tw = tw.BaseTypeWrapper;
|
||||
} while (tw != null && !tw.IsPublic);
|
||||
}
|
||||
|
||||
private void AddType2FieldAccessStubs()
|
||||
{
|
||||
foreach (FieldWrapper fw in wrapper.GetFields())
|
||||
{
|
||||
if ((fw.IsPublic || fw.IsProtected) && !fw.FieldTypeWrapper.IsPublic)
|
||||
{
|
||||
GenerateAccessStub(fw, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateAccessStub(FieldWrapper fw, bool type1)
|
||||
{
|
||||
if (fw is ConstantFieldWrapper)
|
||||
{
|
||||
// constants cannot have a type 2 access stub, because constant types are always public
|
||||
Debug.Assert(type1);
|
||||
|
||||
FieldAttributes attribs = fw.IsPublic ? FieldAttributes.Public : FieldAttributes.FamORAssem;
|
||||
attribs |= FieldAttributes.Static | FieldAttributes.Literal;
|
||||
FieldBuilder fb = typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType, attribs);
|
||||
AttributeHelper.HideFromReflection(fb);
|
||||
fb.SetConstant(((ConstantFieldWrapper)fw).GetConstantValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
string name = fw.Name;
|
||||
// If there is a potential for property name clashes (e.g. we have multiple fields with the same name in this class,
|
||||
// or the current class hides a field in the base class) we will mangle the name as a precaution. We could use a more
|
||||
// complicated scheme which would result in less mangling, but it is exceedingly unlikely to encounter a class with
|
||||
// these field name clashes, because Java cannot handle them either.
|
||||
foreach (FieldWrapper field in wrapper.GetFields())
|
||||
{
|
||||
if (field != fw && !field.IsPrivate && field.Name == name)
|
||||
{
|
||||
name = "<>" + fw.Name + fw.Signature;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Type propType = fw.FieldTypeWrapper.GetPublicBaseTypeWrapper().TypeAsSignatureType;
|
||||
PropertyBuilder pb = typeBuilder.DefineProperty(name, PropertyAttributes.None, propType, Type.EmptyTypes);
|
||||
if (type1)
|
||||
{
|
||||
AttributeHelper.HideFromReflection(pb);
|
||||
}
|
||||
else
|
||||
{
|
||||
AttributeHelper.SetNameSig(pb, fw.Name, fw.Signature);
|
||||
AttributeHelper.SetModifiers(pb, fw.Modifiers, fw.IsInternal);
|
||||
}
|
||||
MethodAttributes attribs = fw.IsPublic ? MethodAttributes.Public : MethodAttributes.FamORAssem;
|
||||
attribs |= MethodAttributes.HideBySig;
|
||||
if (fw.IsStatic)
|
||||
{
|
||||
attribs |= MethodAttributes.Static;
|
||||
}
|
||||
MethodBuilder getter = typeBuilder.DefineMethod(wrapper.GenerateUniqueMethodName("get_" + fw.Name, propType, Type.EmptyTypes), attribs, propType, Type.EmptyTypes);
|
||||
AttributeHelper.HideFromJava(getter);
|
||||
pb.SetGetMethod(getter);
|
||||
CodeEmitter ilgen = CodeEmitter.Create(getter);
|
||||
if (!fw.IsStatic)
|
||||
{
|
||||
ilgen.Emit(OpCodes.Ldarg_0);
|
||||
}
|
||||
fw.EmitGet(ilgen);
|
||||
ilgen.Emit(OpCodes.Ret);
|
||||
if (!fw.IsFinal)
|
||||
{
|
||||
MethodBuilder setter = typeBuilder.DefineMethod(wrapper.GenerateUniqueMethodName("set_" + fw.Name, Types.Void, new Type[] { propType }), attribs, null, new Type[] { propType });
|
||||
AttributeHelper.HideFromJava(setter);
|
||||
pb.SetSetMethod(setter);
|
||||
ilgen = CodeEmitter.Create(setter);
|
||||
ilgen.Emit(OpCodes.Ldarg_0);
|
||||
if (!fw.IsStatic)
|
||||
{
|
||||
ilgen.Emit(OpCodes.Ldarg_1);
|
||||
}
|
||||
if (propType != fw.FieldTypeWrapper.TypeAsSignatureType)
|
||||
{
|
||||
ilgen.Emit(OpCodes.Castclass, fw.FieldTypeWrapper.TypeAsSignatureType);
|
||||
}
|
||||
fw.EmitSet(ilgen);
|
||||
ilgen.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // STATIC_COMPILER
|
||||
|
||||
private void ImplementInterfaceMethodStubs(Dictionary<TypeWrapper, TypeWrapper> doneSet, TypeWrapper interfaceTypeWrapper)
|
||||
{
|
||||
Debug.Assert(interfaceTypeWrapper.IsInterface);
|
||||
|
|
|
@ -1162,7 +1162,7 @@ namespace IKVM.Internal
|
|||
|
||||
private void UpdateNonPublicTypeInSignatureFlag()
|
||||
{
|
||||
if ((IsPublic || IsProtected) && fieldType != null)
|
||||
if ((IsPublic || IsProtected) && fieldType != null && !IsAccessStub)
|
||||
{
|
||||
if (!fieldType.IsPublic && !fieldType.IsUnloadable)
|
||||
{
|
||||
|
@ -1843,91 +1843,6 @@ namespace IKVM.Internal
|
|||
}
|
||||
}
|
||||
|
||||
// This type is used during AOT compilation only!
|
||||
sealed class AotAccessStubFieldWrapper : FieldWrapper
|
||||
{
|
||||
private FieldWrapper basefield;
|
||||
private MethodBuilder getter;
|
||||
private MethodBuilder setter;
|
||||
|
||||
internal AotAccessStubFieldWrapper(TypeWrapper wrapper, FieldWrapper basefield)
|
||||
: base(wrapper, null, basefield.Name, basefield.Signature, basefield.Modifiers, null, MemberFlags.AccessStub | MemberFlags.HideFromReflection)
|
||||
{
|
||||
this.basefield = basefield;
|
||||
}
|
||||
|
||||
private string GenerateUniqueMethodName(string basename, Type returnType, Type[] parameterTypes)
|
||||
{
|
||||
return ((DynamicTypeWrapper)this.DeclaringType).GenerateUniqueMethodName(basename, returnType, parameterTypes);
|
||||
}
|
||||
|
||||
internal void DoLink(TypeBuilder typeBuilder)
|
||||
{
|
||||
basefield.Link();
|
||||
if(basefield is ConstantFieldWrapper)
|
||||
{
|
||||
FieldAttributes attribs = basefield.IsPublic ? FieldAttributes.Public : FieldAttributes.FamORAssem;
|
||||
attribs |= FieldAttributes.Static | FieldAttributes.Literal;
|
||||
FieldBuilder fb = typeBuilder.DefineField(Name, basefield.FieldTypeWrapper.TypeAsSignatureType, attribs);
|
||||
AttributeHelper.HideFromReflection(fb);
|
||||
fb.SetConstant(((ConstantFieldWrapper)basefield).GetConstantValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
Type propType = basefield.FieldTypeWrapper.TypeAsSignatureType;
|
||||
PropertyBuilder pb = typeBuilder.DefineProperty(Name, PropertyAttributes.None, propType, Type.EmptyTypes);
|
||||
AttributeHelper.HideFromReflection(pb);
|
||||
MethodAttributes attribs = basefield.IsPublic ? MethodAttributes.Public : MethodAttributes.FamORAssem;
|
||||
attribs |= MethodAttributes.HideBySig;
|
||||
if(basefield.IsStatic)
|
||||
{
|
||||
attribs |= MethodAttributes.Static;
|
||||
}
|
||||
getter = typeBuilder.DefineMethod(GenerateUniqueMethodName("get_" + Name, propType, Type.EmptyTypes), attribs, propType, Type.EmptyTypes);
|
||||
AttributeHelper.HideFromJava(getter);
|
||||
pb.SetGetMethod(getter);
|
||||
CodeEmitter ilgen = CodeEmitter.Create(getter);
|
||||
if(!basefield.IsStatic)
|
||||
{
|
||||
ilgen.Emit(OpCodes.Ldarg_0);
|
||||
}
|
||||
basefield.EmitGet(ilgen);
|
||||
ilgen.Emit(OpCodes.Ret);
|
||||
if(!basefield.IsFinal)
|
||||
{
|
||||
setter = typeBuilder.DefineMethod(GenerateUniqueMethodName("set_" + Name, Types.Void, new Type[] { propType }), attribs, null, new Type[] { propType });
|
||||
AttributeHelper.HideFromJava(setter);
|
||||
pb.SetSetMethod(setter);
|
||||
ilgen = CodeEmitter.Create(setter);
|
||||
ilgen.Emit(OpCodes.Ldarg_0);
|
||||
if(!basefield.IsStatic)
|
||||
{
|
||||
ilgen.Emit(OpCodes.Ldarg_1);
|
||||
}
|
||||
basefield.EmitSet(ilgen);
|
||||
ilgen.Emit(OpCodes.Ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void EmitGetImpl(CodeEmitter ilgen)
|
||||
{
|
||||
if(basefield is ConstantFieldWrapper)
|
||||
{
|
||||
basefield.EmitGet(ilgen);
|
||||
}
|
||||
else
|
||||
{
|
||||
ilgen.Emit(OpCodes.Call, getter);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void EmitSetImpl(CodeEmitter ilgen)
|
||||
{
|
||||
ilgen.Emit(OpCodes.Call, setter);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CompiledAccessStubFieldWrapper : FieldWrapper
|
||||
{
|
||||
private MethodInfo getter;
|
||||
|
@ -1949,8 +1864,8 @@ namespace IKVM.Internal
|
|||
return modifiers;
|
||||
}
|
||||
|
||||
internal CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property)
|
||||
: base(wrapper, ClassLoaderWrapper.GetWrapperFromType(property.PropertyType), property.Name, ClassLoaderWrapper.GetWrapperFromType(property.PropertyType).SigName, GetModifiers(property), null, MemberFlags.AccessStub | MemberFlags.HideFromReflection)
|
||||
private CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property, TypeWrapper propertyType, string name, string signature, Modifiers modifiers, MemberFlags flags)
|
||||
: base(wrapper, propertyType, name, signature, modifiers, null, flags)
|
||||
{
|
||||
this.getter = property.GetGetMethod(true);
|
||||
this.setter = property.GetSetMethod(true);
|
||||
|
@ -1965,5 +1880,55 @@ namespace IKVM.Internal
|
|||
{
|
||||
ilgen.Emit(OpCodes.Call, setter);
|
||||
}
|
||||
|
||||
internal static bool TryGet(TypeWrapper wrapper, PropertyInfo property, out FieldWrapper accessStub)
|
||||
{
|
||||
NameSigAttribute nameSig = AttributeHelper.GetNameSig(property);
|
||||
bool hideFromReflection = AttributeHelper.IsHideFromReflection(property);
|
||||
|
||||
if (nameSig != null || hideFromReflection)
|
||||
{
|
||||
TypeWrapper type;
|
||||
string name;
|
||||
string sig;
|
||||
if (nameSig == null)
|
||||
{
|
||||
type = ClassLoaderWrapper.GetWrapperFromType(property.PropertyType);
|
||||
name = property.Name;
|
||||
sig = type.SigName;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = ClassFile.FieldTypeWrapperFromSig(wrapper.GetClassLoader(), nameSig.Sig);
|
||||
name = nameSig.Name;
|
||||
sig = nameSig.Sig;
|
||||
}
|
||||
Modifiers modifiers;
|
||||
MemberFlags flags = MemberFlags.AccessStub;
|
||||
if (hideFromReflection)
|
||||
{
|
||||
// it's a Type 1 access stub (to make inherited fields visible)
|
||||
flags |= MemberFlags.HideFromReflection;
|
||||
modifiers = GetModifiers(property);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's a Type 2 access stub (to make fields that have a non-public field type visible)
|
||||
ModifiersAttribute attr = AttributeHelper.GetModifiersAttribute(property);
|
||||
modifiers = attr.Modifiers;
|
||||
if (attr.IsInternal)
|
||||
{
|
||||
flags |= MemberFlags.InternalAccess;
|
||||
}
|
||||
}
|
||||
accessStub = new CompiledAccessStubFieldWrapper(wrapper, property, type, name, sig, modifiers, flags);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
accessStub = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1022,6 +1022,12 @@ namespace IKVM.Internal
|
|||
fb.SetCustomAttribute(customAttributeBuilder);
|
||||
}
|
||||
|
||||
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 });
|
||||
pb.SetCustomAttribute(customAttributeBuilder);
|
||||
}
|
||||
|
||||
internal static byte[] FreezeDryType(Type type)
|
||||
{
|
||||
System.IO.MemoryStream mem = new System.IO.MemoryStream();
|
||||
|
@ -1167,6 +1173,29 @@ namespace IKVM.Internal
|
|||
}
|
||||
}
|
||||
|
||||
internal static NameSigAttribute GetNameSig(PropertyInfo property)
|
||||
{
|
||||
#if !STATIC_COMPILER
|
||||
if(!property.DeclaringType.Assembly.ReflectionOnly)
|
||||
{
|
||||
object[] attr = property.GetCustomAttributes(typeof(NameSigAttribute), false);
|
||||
return attr.Length == 1 ? (NameSigAttribute)attr[0] : null;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
foreach(CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(property))
|
||||
{
|
||||
if(MatchTypes(cad.Constructor.DeclaringType, typeofNameSigAttribute))
|
||||
{
|
||||
IList<CustomAttributeTypedArgument> args = cad.ConstructorArguments;
|
||||
return new NameSigAttribute((string)args[0].Value, (string)args[1].Value);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static NameSigAttribute GetNameSig(MethodBase method)
|
||||
{
|
||||
#if !STATIC_COMPILER
|
||||
|
@ -2931,7 +2960,23 @@ namespace IKVM.Internal
|
|||
|
||||
internal bool IsPackageAccessibleFrom(TypeWrapper wrapper)
|
||||
{
|
||||
return MatchingPackageNames(name, wrapper.name) && InternalsVisibleTo(wrapper);
|
||||
if (MatchingPackageNames(name, wrapper.name))
|
||||
{
|
||||
#if STATIC_COMPILER
|
||||
CompilerClassLoader ccl = GetClassLoader() as CompilerClassLoader;
|
||||
if (ccl != null)
|
||||
{
|
||||
// this is a hack for multi target -sharedclassloader compilation
|
||||
// (during compilation we have multiple CompilerClassLoader instances to represent the single shared runtime class loader)
|
||||
return ccl.IsEquivalentTo(wrapper.GetClassLoader());
|
||||
}
|
||||
#endif
|
||||
return GetClassLoader() == wrapper.GetClassLoader();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool MatchingPackageNames(string name1, string name2)
|
||||
|
@ -3524,6 +3569,21 @@ namespace IKVM.Internal
|
|||
}
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
internal TypeWrapper GetPublicBaseTypeWrapper()
|
||||
{
|
||||
if (this.IsInterface)
|
||||
{
|
||||
return CoreClasses.java.lang.Object.Wrapper;
|
||||
}
|
||||
for (TypeWrapper tw = this; ; tw = tw.BaseTypeWrapper)
|
||||
{
|
||||
if (tw.IsPublic)
|
||||
{
|
||||
return tw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class UnloadableTypeWrapper : TypeWrapper
|
||||
|
@ -4422,11 +4482,12 @@ namespace IKVM.Internal
|
|||
PropertyInfo property = m as PropertyInfo;
|
||||
if(property != null)
|
||||
{
|
||||
// Only AccessStub properties (marked by HideFromReflectionAttribute)
|
||||
// Only AccessStub properties (marked by HideFromReflectionAttribute or NameSigAttribute)
|
||||
// are considered here
|
||||
if(AttributeHelper.IsHideFromReflection(property))
|
||||
FieldWrapper accessStub;
|
||||
if(CompiledAccessStubFieldWrapper.TryGet(this, property, out accessStub))
|
||||
{
|
||||
fields.Add(new CompiledAccessStubFieldWrapper(this, property));
|
||||
fields.Add(accessStub);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -319,7 +319,7 @@ sealed class Compiler
|
|||
v.type != VerifierTypeWrapper.UninitializedThis &&
|
||||
(v.type != tw || tw.TypeAsLocalOrStackType != tw.TypeAsSignatureType))
|
||||
{
|
||||
v.builder = ilGenerator.DeclareLocal(v.type.TypeAsLocalOrStackType);
|
||||
v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type));
|
||||
if(debug && v.name != null)
|
||||
{
|
||||
v.builder.SetLocalSymInfo(v.name);
|
||||
|
@ -763,7 +763,7 @@ sealed class Compiler
|
|||
else
|
||||
{
|
||||
types[i] = StackType.Other;
|
||||
locals[i] = compiler.ilGenerator.AllocTempLocal(type.TypeAsLocalOrStackType);
|
||||
locals[i] = compiler.ilGenerator.AllocTempLocal(compiler.GetLocalBuilderType(type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1852,7 +1852,7 @@ sealed class Compiler
|
|||
// this could be done a little more efficiently, but since in practice this
|
||||
// code never runs (for code compiled from Java source) it doesn't
|
||||
// really matter
|
||||
LocalBuilder newobj = ilGenerator.DeclareLocal(thisType.TypeAsLocalOrStackType);
|
||||
LocalBuilder newobj = ilGenerator.DeclareLocal(GetLocalBuilderType(thisType));
|
||||
ilGenerator.Emit(OpCodes.Stloc, newobj);
|
||||
LocalBuilder[] tempstack = new LocalBuilder[stackfix.Length];
|
||||
for(int j = 0; j < stackfix.Length; j++)
|
||||
|
@ -1870,7 +1870,7 @@ sealed class Compiler
|
|||
}
|
||||
else if(!VerifierTypeWrapper.IsNew(stacktype))
|
||||
{
|
||||
LocalBuilder lb = ilGenerator.DeclareLocal(stacktype.TypeAsLocalOrStackType);
|
||||
LocalBuilder lb = ilGenerator.DeclareLocal(GetLocalBuilderType(stacktype));
|
||||
ilGenerator.Emit(OpCodes.Stloc, lb);
|
||||
tempstack[j] = lb;
|
||||
}
|
||||
|
@ -1903,7 +1903,7 @@ sealed class Compiler
|
|||
if(locals[j].builder == null)
|
||||
{
|
||||
// for invokespecial the resulting type can never be null
|
||||
locals[j].builder = ilGenerator.DeclareLocal(locals[j].type.TypeAsLocalOrStackType);
|
||||
locals[j].builder = ilGenerator.DeclareLocal(GetLocalBuilderType(locals[j].type));
|
||||
}
|
||||
ilGenerator.Emit(OpCodes.Ldloc, newobj);
|
||||
ilGenerator.Emit(OpCodes.Stloc, locals[j].builder);
|
||||
|
@ -1937,7 +1937,7 @@ sealed class Compiler
|
|||
if(locals[j].builder == null)
|
||||
{
|
||||
// for invokespecial the resulting type can never be null
|
||||
locals[j].builder = ilGenerator.DeclareLocal(locals[j].type.TypeAsLocalOrStackType);
|
||||
locals[j].builder = ilGenerator.DeclareLocal(GetLocalBuilderType(locals[j].type));
|
||||
}
|
||||
ilGenerator.Emit(OpCodes.Ldarg_0);
|
||||
ilGenerator.Emit(OpCodes.Stloc, locals[j].builder);
|
||||
|
@ -3104,7 +3104,7 @@ sealed class Compiler
|
|||
else if(args[i].IsInterfaceOrInterfaceArray)
|
||||
{
|
||||
TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i);
|
||||
if(!tw.IsUnloadable && !tw.IsAssignableTo(args[i]))
|
||||
if(tw.IsUnloadable || NeedsInterfaceDownCast(tw, args[i]))
|
||||
{
|
||||
needsCast = true;
|
||||
firstCastArg = i;
|
||||
|
@ -3153,7 +3153,7 @@ sealed class Compiler
|
|||
if(!args[i].IsUnloadable && !args[i].IsGhost)
|
||||
{
|
||||
TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i);
|
||||
if(tw.IsUnloadable || (args[i].IsInterfaceOrInterfaceArray && !tw.IsAssignableTo(args[i])))
|
||||
if(tw.IsUnloadable || (args[i].IsInterfaceOrInterfaceArray && NeedsInterfaceDownCast(tw, args[i])))
|
||||
{
|
||||
ilGenerator.EmitAssertType(args[i].TypeAsTBD);
|
||||
Profiler.Count("InterfaceDownCast");
|
||||
|
@ -3225,6 +3225,15 @@ sealed class Compiler
|
|||
}
|
||||
}
|
||||
|
||||
private bool NeedsInterfaceDownCast(TypeWrapper tw, TypeWrapper arg)
|
||||
{
|
||||
if (!tw.IsAccessibleFrom(clazz))
|
||||
{
|
||||
tw = tw.GetPublicBaseTypeWrapper();
|
||||
}
|
||||
return !tw.IsAssignableTo(arg);
|
||||
}
|
||||
|
||||
private void DynamicGetPutField(Instruction instr, int i)
|
||||
{
|
||||
NormalizedByteCode bytecode = instr.NormalizedOpCode;
|
||||
|
@ -3470,7 +3479,7 @@ sealed class Compiler
|
|||
{
|
||||
if(v.builder == null)
|
||||
{
|
||||
v.builder = ilGenerator.DeclareLocal(v.type.TypeAsLocalOrStackType);
|
||||
v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type));
|
||||
if(debug && v.name != null)
|
||||
{
|
||||
v.builder.SetLocalSymInfo(v.name);
|
||||
|
@ -3510,7 +3519,7 @@ sealed class Compiler
|
|||
{
|
||||
if(v.builder == null)
|
||||
{
|
||||
v.builder = ilGenerator.DeclareLocal(v.type.TypeAsLocalOrStackType);
|
||||
v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type));
|
||||
if(debug && v.name != null)
|
||||
{
|
||||
v.builder.SetLocalSymInfo(v.name);
|
||||
|
@ -3520,4 +3529,20 @@ sealed class Compiler
|
|||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private Type GetLocalBuilderType(TypeWrapper tw)
|
||||
{
|
||||
if (tw.IsUnloadable)
|
||||
{
|
||||
return Types.Object;
|
||||
}
|
||||
else if (tw.IsAccessibleFrom(clazz))
|
||||
{
|
||||
return tw.TypeAsLocalOrStackType;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tw.GetPublicBaseTypeWrapper().TypeAsLocalOrStackType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче