- 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:
jfrijters 2009-11-13 15:08:20 +00:00
Родитель c8dd69be99
Коммит c7ae133d38
5 изменённых файлов: 313 добавлений и 160 удалений

Просмотреть файл

@ -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;
}
}
}