зеркало из 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;
|
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)
|
internal override bool InternalsVisibleToImpl(TypeWrapper wrapper, TypeWrapper friend)
|
||||||
{
|
{
|
||||||
Debug.Assert(wrapper.GetClassLoader() == this);
|
Debug.Assert(wrapper.GetClassLoader() == this);
|
||||||
|
@ -442,19 +462,18 @@ namespace IKVM.Internal
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
CompilerClassLoader ccl = other as CompilerClassLoader;
|
CompilerClassLoader ccl = other as CompilerClassLoader;
|
||||||
if (ccl != null
|
if (ccl != null)
|
||||||
&& options.sharedclassloader != null
|
|
||||||
&& options.sharedclassloader.Contains(ccl))
|
|
||||||
{
|
{
|
||||||
AddInternalsVisibleToAttribute(ccl.assemblyBuilder);
|
AddInternalsVisibleToAttribute(ccl);
|
||||||
internalsVisibleTo.Add(other);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddInternalsVisibleToAttribute(AssemblyBuilder asm)
|
private void AddInternalsVisibleToAttribute(CompilerClassLoader ccl)
|
||||||
{
|
{
|
||||||
|
internalsVisibleTo.Add(ccl);
|
||||||
|
AssemblyBuilder asm = ccl.assemblyBuilder;
|
||||||
AssemblyName asmName = asm.GetName();
|
AssemblyName asmName = asm.GetName();
|
||||||
string name = asmName.Name;
|
string name = asmName.Name;
|
||||||
byte[] pubkey = asmName.GetPublicKey();
|
byte[] pubkey = asmName.GetPublicKey();
|
||||||
|
|
|
@ -547,12 +547,6 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if STATIC_COMPILER
|
#if STATIC_COMPILER
|
||||||
if (wrapper.IsPublic)
|
|
||||||
{
|
|
||||||
List<FieldWrapper> fieldsArray = new List<FieldWrapper>(fields);
|
|
||||||
AddAccessStubFields(fieldsArray, wrapper);
|
|
||||||
fields = fieldsArray.ToArray();
|
|
||||||
}
|
|
||||||
((AotTypeWrapper)wrapper).AddMapXmlFields(ref fields);
|
((AotTypeWrapper)wrapper).AddMapXmlFields(ref fields);
|
||||||
#endif
|
#endif
|
||||||
wrapper.SetFields(fields);
|
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)
|
private static bool CheckInnerOuterNames(string inner, string outer)
|
||||||
{
|
{
|
||||||
// do some sanity checks on the inner/outer class names
|
// do some sanity checks on the inner/outer class names
|
||||||
|
@ -1252,11 +1223,6 @@ namespace IKVM.Internal
|
||||||
|
|
||||||
internal override FieldInfo LinkField(FieldWrapper fw)
|
internal override FieldInfo LinkField(FieldWrapper fw)
|
||||||
{
|
{
|
||||||
if (fw.IsAccessStub)
|
|
||||||
{
|
|
||||||
((AotAccessStubFieldWrapper)fw).DoLink(typeBuilder);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (fw is DynamicPropertyFieldWrapper)
|
if (fw is DynamicPropertyFieldWrapper)
|
||||||
{
|
{
|
||||||
((DynamicPropertyFieldWrapper)fw).DoLink(typeBuilder);
|
((DynamicPropertyFieldWrapper)fw).DoLink(typeBuilder);
|
||||||
|
@ -1313,6 +1279,7 @@ namespace IKVM.Internal
|
||||||
MethodAttributes methodAttribs = MethodAttributes.HideBySig;
|
MethodAttributes methodAttribs = MethodAttributes.HideBySig;
|
||||||
#if STATIC_COMPILER
|
#if STATIC_COMPILER
|
||||||
bool setModifiers = fld.IsInternal || (fld.Modifiers & (Modifiers.Synthetic | Modifiers.Enum)) != 0;
|
bool setModifiers = fld.IsInternal || (fld.Modifiers & (Modifiers.Synthetic | Modifiers.Enum)) != 0;
|
||||||
|
bool hideFromJava = false;
|
||||||
#endif
|
#endif
|
||||||
bool isWrappedFinal = false;
|
bool isWrappedFinal = false;
|
||||||
if (fld.IsPrivate)
|
if (fld.IsPrivate)
|
||||||
|
@ -1334,6 +1301,17 @@ namespace IKVM.Internal
|
||||||
attribs |= FieldAttributes.Assembly;
|
attribs |= FieldAttributes.Assembly;
|
||||||
methodAttribs |= MethodAttributes.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)
|
if (fld.IsStatic)
|
||||||
{
|
{
|
||||||
attribs |= FieldAttributes.Static;
|
attribs |= FieldAttributes.Static;
|
||||||
|
@ -1391,6 +1369,10 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
AttributeHelper.SetConstantValue(field, constantValue);
|
AttributeHelper.SetConstantValue(field, constantValue);
|
||||||
}
|
}
|
||||||
|
if (hideFromJava)
|
||||||
|
{
|
||||||
|
AttributeHelper.HideFromJava(field);
|
||||||
|
}
|
||||||
#endif // STATIC_COMPILER
|
#endif // STATIC_COMPILER
|
||||||
if (isWrappedFinal)
|
if (isWrappedFinal)
|
||||||
{
|
{
|
||||||
|
@ -1511,30 +1493,12 @@ namespace IKVM.Internal
|
||||||
classFile.Link(wrapper);
|
classFile.Link(wrapper);
|
||||||
for (int i = 0; i < fields.Length; i++)
|
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();
|
fields[i].Link();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < methods.Length; i++)
|
for (int i = 0; i < methods.Length; i++)
|
||||||
{
|
{
|
||||||
methods[i].Link();
|
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,
|
// 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.
|
// so it needs to be protected by a lock.
|
||||||
lock (this)
|
lock (this)
|
||||||
|
@ -3911,6 +3875,13 @@ namespace IKVM.Internal
|
||||||
|
|
||||||
// See if there is any additional metadata
|
// See if there is any additional metadata
|
||||||
wrapper.EmitMapXmlMetadata(typeBuilder, classFile, fields, methods);
|
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
|
#endif // STATIC_COMPILER
|
||||||
|
|
||||||
for (int i = 0; i < classFile.Methods.Length; i++)
|
for (int i = 0; i < classFile.Methods.Length; i++)
|
||||||
|
@ -4083,6 +4054,118 @@ namespace IKVM.Internal
|
||||||
return type;
|
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)
|
private void ImplementInterfaceMethodStubs(Dictionary<TypeWrapper, TypeWrapper> doneSet, TypeWrapper interfaceTypeWrapper)
|
||||||
{
|
{
|
||||||
Debug.Assert(interfaceTypeWrapper.IsInterface);
|
Debug.Assert(interfaceTypeWrapper.IsInterface);
|
||||||
|
|
|
@ -1162,7 +1162,7 @@ namespace IKVM.Internal
|
||||||
|
|
||||||
private void UpdateNonPublicTypeInSignatureFlag()
|
private void UpdateNonPublicTypeInSignatureFlag()
|
||||||
{
|
{
|
||||||
if ((IsPublic || IsProtected) && fieldType != null)
|
if ((IsPublic || IsProtected) && fieldType != null && !IsAccessStub)
|
||||||
{
|
{
|
||||||
if (!fieldType.IsPublic && !fieldType.IsUnloadable)
|
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
|
sealed class CompiledAccessStubFieldWrapper : FieldWrapper
|
||||||
{
|
{
|
||||||
private MethodInfo getter;
|
private MethodInfo getter;
|
||||||
|
@ -1949,8 +1864,8 @@ namespace IKVM.Internal
|
||||||
return modifiers;
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property)
|
private CompiledAccessStubFieldWrapper(TypeWrapper wrapper, PropertyInfo property, TypeWrapper propertyType, string name, string signature, Modifiers modifiers, MemberFlags flags)
|
||||||
: base(wrapper, ClassLoaderWrapper.GetWrapperFromType(property.PropertyType), property.Name, ClassLoaderWrapper.GetWrapperFromType(property.PropertyType).SigName, GetModifiers(property), null, MemberFlags.AccessStub | MemberFlags.HideFromReflection)
|
: base(wrapper, propertyType, name, signature, modifiers, null, flags)
|
||||||
{
|
{
|
||||||
this.getter = property.GetGetMethod(true);
|
this.getter = property.GetGetMethod(true);
|
||||||
this.setter = property.GetSetMethod(true);
|
this.setter = property.GetSetMethod(true);
|
||||||
|
@ -1965,5 +1880,55 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
ilgen.Emit(OpCodes.Call, setter);
|
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);
|
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)
|
internal static byte[] FreezeDryType(Type type)
|
||||||
{
|
{
|
||||||
System.IO.MemoryStream mem = new System.IO.MemoryStream();
|
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)
|
internal static NameSigAttribute GetNameSig(MethodBase method)
|
||||||
{
|
{
|
||||||
#if !STATIC_COMPILER
|
#if !STATIC_COMPILER
|
||||||
|
@ -2931,7 +2960,23 @@ namespace IKVM.Internal
|
||||||
|
|
||||||
internal bool IsPackageAccessibleFrom(TypeWrapper wrapper)
|
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)
|
private static bool MatchingPackageNames(string name1, string name2)
|
||||||
|
@ -3524,6 +3569,21 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
return interfaces;
|
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
|
sealed class UnloadableTypeWrapper : TypeWrapper
|
||||||
|
@ -4422,11 +4482,12 @@ namespace IKVM.Internal
|
||||||
PropertyInfo property = m as PropertyInfo;
|
PropertyInfo property = m as PropertyInfo;
|
||||||
if(property != null)
|
if(property != null)
|
||||||
{
|
{
|
||||||
// Only AccessStub properties (marked by HideFromReflectionAttribute)
|
// Only AccessStub properties (marked by HideFromReflectionAttribute or NameSigAttribute)
|
||||||
// are considered here
|
// 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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -319,7 +319,7 @@ sealed class Compiler
|
||||||
v.type != VerifierTypeWrapper.UninitializedThis &&
|
v.type != VerifierTypeWrapper.UninitializedThis &&
|
||||||
(v.type != tw || tw.TypeAsLocalOrStackType != tw.TypeAsSignatureType))
|
(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)
|
if(debug && v.name != null)
|
||||||
{
|
{
|
||||||
v.builder.SetLocalSymInfo(v.name);
|
v.builder.SetLocalSymInfo(v.name);
|
||||||
|
@ -763,7 +763,7 @@ sealed class Compiler
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
types[i] = StackType.Other;
|
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
|
// 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
|
// code never runs (for code compiled from Java source) it doesn't
|
||||||
// really matter
|
// really matter
|
||||||
LocalBuilder newobj = ilGenerator.DeclareLocal(thisType.TypeAsLocalOrStackType);
|
LocalBuilder newobj = ilGenerator.DeclareLocal(GetLocalBuilderType(thisType));
|
||||||
ilGenerator.Emit(OpCodes.Stloc, newobj);
|
ilGenerator.Emit(OpCodes.Stloc, newobj);
|
||||||
LocalBuilder[] tempstack = new LocalBuilder[stackfix.Length];
|
LocalBuilder[] tempstack = new LocalBuilder[stackfix.Length];
|
||||||
for(int j = 0; j < stackfix.Length; j++)
|
for(int j = 0; j < stackfix.Length; j++)
|
||||||
|
@ -1870,7 +1870,7 @@ sealed class Compiler
|
||||||
}
|
}
|
||||||
else if(!VerifierTypeWrapper.IsNew(stacktype))
|
else if(!VerifierTypeWrapper.IsNew(stacktype))
|
||||||
{
|
{
|
||||||
LocalBuilder lb = ilGenerator.DeclareLocal(stacktype.TypeAsLocalOrStackType);
|
LocalBuilder lb = ilGenerator.DeclareLocal(GetLocalBuilderType(stacktype));
|
||||||
ilGenerator.Emit(OpCodes.Stloc, lb);
|
ilGenerator.Emit(OpCodes.Stloc, lb);
|
||||||
tempstack[j] = lb;
|
tempstack[j] = lb;
|
||||||
}
|
}
|
||||||
|
@ -1903,7 +1903,7 @@ sealed class Compiler
|
||||||
if(locals[j].builder == null)
|
if(locals[j].builder == null)
|
||||||
{
|
{
|
||||||
// for invokespecial the resulting type can never be 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.Ldloc, newobj);
|
||||||
ilGenerator.Emit(OpCodes.Stloc, locals[j].builder);
|
ilGenerator.Emit(OpCodes.Stloc, locals[j].builder);
|
||||||
|
@ -1937,7 +1937,7 @@ sealed class Compiler
|
||||||
if(locals[j].builder == null)
|
if(locals[j].builder == null)
|
||||||
{
|
{
|
||||||
// for invokespecial the resulting type can never be 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.Ldarg_0);
|
||||||
ilGenerator.Emit(OpCodes.Stloc, locals[j].builder);
|
ilGenerator.Emit(OpCodes.Stloc, locals[j].builder);
|
||||||
|
@ -3104,7 +3104,7 @@ sealed class Compiler
|
||||||
else if(args[i].IsInterfaceOrInterfaceArray)
|
else if(args[i].IsInterfaceOrInterfaceArray)
|
||||||
{
|
{
|
||||||
TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i);
|
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;
|
needsCast = true;
|
||||||
firstCastArg = i;
|
firstCastArg = i;
|
||||||
|
@ -3153,7 +3153,7 @@ sealed class Compiler
|
||||||
if(!args[i].IsUnloadable && !args[i].IsGhost)
|
if(!args[i].IsUnloadable && !args[i].IsGhost)
|
||||||
{
|
{
|
||||||
TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i);
|
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);
|
ilGenerator.EmitAssertType(args[i].TypeAsTBD);
|
||||||
Profiler.Count("InterfaceDownCast");
|
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)
|
private void DynamicGetPutField(Instruction instr, int i)
|
||||||
{
|
{
|
||||||
NormalizedByteCode bytecode = instr.NormalizedOpCode;
|
NormalizedByteCode bytecode = instr.NormalizedOpCode;
|
||||||
|
@ -3470,7 +3479,7 @@ sealed class Compiler
|
||||||
{
|
{
|
||||||
if(v.builder == null)
|
if(v.builder == null)
|
||||||
{
|
{
|
||||||
v.builder = ilGenerator.DeclareLocal(v.type.TypeAsLocalOrStackType);
|
v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type));
|
||||||
if(debug && v.name != null)
|
if(debug && v.name != null)
|
||||||
{
|
{
|
||||||
v.builder.SetLocalSymInfo(v.name);
|
v.builder.SetLocalSymInfo(v.name);
|
||||||
|
@ -3510,7 +3519,7 @@ sealed class Compiler
|
||||||
{
|
{
|
||||||
if(v.builder == null)
|
if(v.builder == null)
|
||||||
{
|
{
|
||||||
v.builder = ilGenerator.DeclareLocal(v.type.TypeAsLocalOrStackType);
|
v.builder = ilGenerator.DeclareLocal(GetLocalBuilderType(v.type));
|
||||||
if(debug && v.name != null)
|
if(debug && v.name != null)
|
||||||
{
|
{
|
||||||
v.builder.SetLocalSymInfo(v.name);
|
v.builder.SetLocalSymInfo(v.name);
|
||||||
|
@ -3520,4 +3529,20 @@ sealed class Compiler
|
||||||
}
|
}
|
||||||
return v;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче