Implemented type 2 access stubs for methods (not constructors) and rewrote how type 1 access stubs are handled.

This commit is contained in:
jfrijters 2011-11-23 06:20:34 +00:00
Родитель 46828f2616
Коммит 44c6177691
5 изменённых файлов: 219 добавлений и 255 удалений

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

@ -404,7 +404,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.XML.Transform.dll
-baseaddress:0x57EC0000
-baseaddress:0x57EF0000
@OPENJDK7@/build/linux-amd64/impsrc/com/sun/java_cup/internal/runtime/*.class
@OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/apache/bcel/internal/*.class
@OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/apache/bcel/internal/classfile/*.class
@ -428,7 +428,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.XML.Bind.dll
-baseaddress:0x58310000
-baseaddress:0x58340000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/javax/xml/bind/*
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/xml/internal/bind/*
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/xml/internal/fastinfoset/*
@ -487,7 +487,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.XML.WebServices.dll
-baseaddress:0x586A0000
-baseaddress:0x586D0000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/xml/internal/messaging/*
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/xml/internal/ws/*
@OPENJDK7@/build/linux-amd64/impsrc/com/sun/org/glassfish/external/amx/*.class
@ -607,7 +607,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.XML.Crypto.dll
-baseaddress:0x58C10000
-baseaddress:0x58C40000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/org/apache/xml/internal/security/*
@OPENJDK7@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/*.class
@OPENJDK7@/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/*.class
@ -643,7 +643,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.SwingAWT.dll
-baseaddress:0x58D60000
-baseaddress:0x58D90000
-remap:swingawt.xml
-resource:META-INF/services/sun.java2d.pipe.RenderingEngine=resources/META-INF/services/sun.java2d.pipe.RenderingEngine
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/META-INF/services/sun.java2d.cmm.PCMM
@ -743,7 +743,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Charsets.dll
-baseaddress:0x59F60000
-baseaddress:0x59F90000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/charsets.jar/sun/nio/cs/ext/sjis0213.dat
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/charsets.jar/META-INF/services/java.nio.charset.spi.CharsetProvider
@OPENJDK7@/build/linux-amd64/gensrc/sun/nio/cs/ext/*.class
@ -752,7 +752,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Util.dll
-baseaddress:0x5A5F0000
-baseaddress:0x5A620000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/java/util/jar/pack/intrinsic.properties
-resource:META-INF/services/java.nio.file.spi.FileSystemProvider=@OPENJDK7@/jdk/src/share/demo/nio/zipfs/src/META-INF/services/java.nio.file.spi.FileSystemProvider
java/util/zip/*.class
@ -773,7 +773,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Text.dll
-baseaddress:0x5AB90000
-baseaddress:0x5ABC0000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/sun/text/*
@OPENJDK7@/build/linux-amd64/j2re-image/lib/ext/localedata.jar
@OPENJDK7@/jdk/src/share/classes/java/text/*.class
@ -785,7 +785,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Security.dll
-baseaddress:0x5AE00000
-baseaddress:0x5AE30000
-remap:security.xml
sun/security/jgss/wrapper/*.class
@OPENJDK7@/jdk/src/share/classes/com/sun/crypto/provider/*.class
@ -856,7 +856,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Management.dll
-baseaddress:0x5B5E0000
-baseaddress:0x5B610000
com/sun/management/*.class
java/lang/management/*.class
sun/management/*.class
@ -890,7 +890,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Misc.dll
-baseaddress:0x5B940000
-baseaddress:0x5B970000
-resource:com/sun/servicetag/resources/javase_5_swordfish.properties=@OPENJDK7@/jdk/src/share/classes/com/sun/servicetag/resources/javase_5_swordfish.properties
-resource:com/sun/servicetag/resources/javase_6_swordfish.properties=@OPENJDK7@/jdk/src/share/classes/com/sun/servicetag/resources/javase_6_swordfish.properties
-resource:com/sun/servicetag/resources/javase_7_swordfish.properties=@OPENJDK7@/jdk/src/share/classes/com/sun/servicetag/resources/javase_7_swordfish.properties
@ -991,7 +991,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Naming.dll
-baseaddress:0x5BA30000
-baseaddress:0x5BA60000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/jndi/ldap/jndiprovider.properties
-resource:META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor=@OPENJDK7@/jdk/src/share/classes/sun/net/spi/nameservice/dns/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor
sun/net/dns/*.class
@ -1017,7 +1017,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Jdbc.dll
-baseaddress:0x5BB80000
-baseaddress:0x5BBB0000
-resource:META-INF/services/java.sql.Driver=resources/META-INF/services/java.sql.Driver
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/rowset/*
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/javax/sql/*
@ -1035,7 +1035,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Remoting.dll
-baseaddress:0x5BCD0000
-baseaddress:0x5BD00000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/sun/rmi/*
@OPENJDK7@/build/linux-amd64/classes/sun/rmi/registry/*.class
@OPENJDK7@/build/linux-amd64/classes/sun/rmi/server/*.class
@ -1061,7 +1061,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Beans.dll
-baseaddress:0x5BDF0000
-baseaddress:0x5BE20000
@OPENJDK7@/build/linux-amd64/impsrc/com/sun/activation/registries/*.class
@OPENJDK7@/build/linux-amd64/impsrc/javax/activation/*.class
@OPENJDK7@/jdk/src/share/classes/com/sun/beans/*.class
@ -1074,7 +1074,7 @@ assembly.class
}
{
-out:IKVM.OpenJDK.Media.dll
-baseaddress:0x5BEB0000
-baseaddress:0x5BEE0000
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/META-INF/services/javax.print.*
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/META-INF/services/javax.sound.*
-recurse:@OPENJDK7@/build/linux-amd64/j2re-image/lib/resources.jar/com/sun/imageio/plugins/common/iio-plugin.properties

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

@ -2431,7 +2431,11 @@ namespace IKVM.Internal
{
break;
}
if (baseMethod2.DeclaringType.IsPackageAccessibleFrom(wrapper) && !baseMethod2.IsPrivate)
if (baseMethod2.IsAccessStub)
{
// ignore
}
else if (baseMethod2.DeclaringType.IsPackageAccessibleFrom(wrapper) && !baseMethod2.IsPrivate)
{
if (baseMethod2.IsFinal)
{
@ -2540,7 +2544,11 @@ namespace IKVM.Internal
{
break;
}
if (baseMethod2.DeclaringType.IsPackageAccessibleFrom(wrapper) && !baseMethod2.IsPrivate)
if (baseMethod2.IsAccessStub)
{
// ignore
}
else if (baseMethod2.DeclaringType.IsPackageAccessibleFrom(wrapper) && !baseMethod2.IsPrivate)
{
if (baseMethod2.IsFinal)
{
@ -4149,12 +4157,10 @@ 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 we inherit public members from non-public base classes or have public members with non-public types in their signature, we need access stubs
if (wrapper.IsPublic)
{
AddType1FieldAccessStubs(wrapper);
AddType2FieldAccessStubs();
AddType1MethodAccessStubs();
AddAccessStubs();
}
#endif // STATIC_COMPILER
@ -4336,7 +4342,44 @@ namespace IKVM.Internal
}
#if STATIC_COMPILER
private void AddType1FieldAccessStubs(TypeWrapper tw)
private void AddAccessStubs()
{
/*
* There are two types of access stubs:
*
* Type 1 These are required when a public class extends a non-public class.
* In that case we need access stubs for all public and protected members
* of the non-public base classes.
*
* Type 2 When a public class exposes a member that contains a non-public type in
* its signature, we need an access stub for that member (where we convert
* the non-public type in the signature to the first public base type).
*
* Note that type 1 access stubs may also need the type 2 signature type widening
* if the signature contains non-public types.
*
* Type 1 access stubs are always required, because the JVM allow access to these
* members via the derived class while the CLR doesn't. Historically, we've exposed
* these access stubs in such a way that they are also consumable from other .NET
* languages (when feasible), so we'll continue to do that for back compat.
*
* Type 2 access stubs are only required by the CLR when running on CLR v4 and the
* caller assembly is security transparent code (level 2). We also want the access
* stubs to allow other .NET languages (e.g. C#) to consume broken APIs that
* (accidentally) expose these members.
*/
List<string> propertyNames = null;
AddType2FieldAccessStubs(ref propertyNames);
AddType1FieldAccessStubs(wrapper, ref propertyNames);
if (!wrapper.IsInterface)
{
int id = 0;
AddType2MethodAccessStubs(ref id);
AddType1MethodAccessStubs(ref id);
}
}
private void AddType1FieldAccessStubs(TypeWrapper tw, ref List<string> propertyNames)
{
do
{
@ -4347,36 +4390,64 @@ namespace IKVM.Internal
if ((fw.IsPublic || fw.IsProtected)
&& wrapper.GetFieldWrapper(fw.Name, fw.Signature) == fw)
{
GenerateAccessStub(fw, true);
GenerateAccessStub(fw, ref propertyNames, true);
}
}
}
foreach (TypeWrapper iface in tw.Interfaces)
{
AddType1FieldAccessStubs(iface);
AddType1FieldAccessStubs(iface, ref propertyNames);
}
tw = tw.BaseTypeWrapper;
} while (tw != null && !tw.IsPublic);
}
private void AddType2FieldAccessStubs()
private void AddType2FieldAccessStubs(ref List<string> propertyNames)
{
foreach (FieldWrapper fw in wrapper.GetFields())
{
if (fw.HasNonPublicTypeInSignature)
if (fw.HasNonPublicTypeInSignature && fw.FieldTypeWrapper.IsAccessibleFrom(wrapper))
{
GenerateAccessStub(fw, false);
GenerateAccessStub(fw, ref propertyNames, false);
}
}
}
private void GenerateAccessStub(FieldWrapper fw, bool type1)
private void GenerateAccessStub(FieldWrapper fw, ref List<string> propertyNames, bool type1)
{
string name = fw.Name;
if (propertyNames == null)
{
propertyNames = new List<string>();
// add all the fields, to avoid clashing with real fields (which can happen for type 2 or type 1 if field type is non-public or unloadable)
foreach (FieldWrapper fw1 in wrapper.GetFields())
{
if (!fw1.HasNonPublicTypeInSignature)
{
propertyNames.Add(fw1.Name);
}
}
}
int uniq = 0;
while (propertyNames.Contains(name))
{
// when we clash, we don't want the access stub property to be visible from (e.g.) C# so we mangle the name
name = "<>" + fw.Name + "_" + uniq++;
}
propertyNames.Add(name);
if (fw is ConstantFieldWrapper)
{
// constants cannot have a type 2 access stub, because constant types are always public
Debug.Assert(type1);
if (uniq != 0)
{
// we only add access stubs for constant fields for consumption by other languages,
// so when the field is hidden by another field, we don't need to bother
return;
}
FieldAttributes attribs = fw.IsPublic ? FieldAttributes.Public : FieldAttributes.FamORAssem;
attribs |= FieldAttributes.Static | FieldAttributes.Literal;
FieldBuilder fb = typeBuilder.DefineField(fw.Name, fw.FieldTypeWrapper.TypeAsSignatureType, attribs);
@ -4385,25 +4456,12 @@ namespace IKVM.Internal
}
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;
Type propType = ToPublicSignatureType(fw.FieldTypeWrapper);
PropertyBuilder pb = typeBuilder.DefineProperty(name, PropertyAttributes.None, propType, Type.EmptyTypes);
if (type1)
{
AttributeHelper.HideFromReflection(pb);
if (fw.HasNonPublicTypeInSignature)
if (fw.HasNonPublicTypeInSignature || fw.FieldTypeWrapper.IsUnloadable)
{
AttributeHelper.SetNameSig(pb, fw.Name, fw.Signature);
}
@ -4447,6 +4505,7 @@ namespace IKVM.Internal
{
ilgen.Emit(OpCodes.Ldarg_1);
}
// we don't do a DynamicCast if fw.FieldTypeWrapper is unloadable, because for normal unloadable fields we don't enfore the type either
if (propType != fw.FieldTypeWrapper.TypeAsSignatureType)
{
ilgen.Emit(OpCodes.Castclass, fw.FieldTypeWrapper.TypeAsSignatureType);
@ -4458,96 +4517,48 @@ namespace IKVM.Internal
}
}
private void AddType1MethodAccessStubs()
private void AddType1MethodAccessStubs(ref int id)
{
for (int pass = 0; pass < 2; pass++)
for (TypeWrapper tw = wrapper.BaseTypeWrapper; tw != null && !tw.IsPublic; tw = tw.BaseTypeWrapper)
{
for (TypeWrapper tw = wrapper.BaseTypeWrapper; tw != null && !tw.IsPublic; tw = tw.BaseTypeWrapper)
foreach (MethodWrapper mw in tw.GetMethods())
{
foreach (MethodWrapper mw in tw.GetMethods())
if ((mw.IsPublic || mw.IsProtected)
&& (!mw.IsAbstract || wrapper.IsAbstract)
&& mw.Name != StringConstants.INIT
&& wrapper.GetMethodWrapper(mw.Name, mw.Signature, true) == mw
&& ParametersAreAccessible(mw))
{
if ((mw.IsPublic || mw.IsProtected)
&& (!mw.IsAbstract || wrapper.IsAbstract)
&& mw.Name != StringConstants.INIT
&& wrapper.GetMethodWrapper(mw.Name, mw.Signature, true) == mw)
GenerateAccessStub(id, mw, true, true);
if (!mw.IsStatic && !mw.IsFinal && !mw.IsAbstract)
{
// we generate type 1a in the first pass, because it can't deal with name collisions
if (pass == 0)
{
if (!mw.HasNonPublicTypeInSignature)
{
GenerateType1aAccessStub(mw);
}
}
else
{
if (mw.HasNonPublicTypeInSignature)
{
GenerateType1bAccessStub(mw, true);
if (!wrapper.IsFinal && !mw.IsStatic)
{
GenerateType1bAccessStub(mw, false);
}
}
}
GenerateAccessStub(id, mw, false, true);
}
id++;
}
}
}
}
private void GenerateType1aAccessStub(MethodWrapper mw)
private void AddType2MethodAccessStubs(ref int id)
{
Debug.Assert(!mw.HasCallerID);
MethodAttributes stubattribs = mw.IsPublic ? MethodAttributes.Public : MethodAttributes.FamORAssem;
stubattribs |= MethodAttributes.HideBySig;
if (mw.IsStatic)
foreach (MethodWrapper mw in wrapper.GetMethods())
{
stubattribs |= MethodAttributes.Static;
}
else
{
stubattribs |= MethodAttributes.CheckAccessOnOverride | MethodAttributes.Virtual;
if (mw.IsAbstract)
if (mw.HasNonPublicTypeInSignature
&& mw.Name != StringConstants.INIT // TODO we don't currently support constructors
&& ParametersAreAccessible(mw))
{
stubattribs |= MethodAttributes.Abstract;
GenerateAccessStub(id, mw, true, false);
if (!mw.IsStatic && !mw.IsFinal && !mw.IsAbstract)
{
GenerateAccessStub(id, mw, false, false);
}
id++;
}
if (mw.IsFinal)
{
// NOTE final methods still need to be virtual, because a subclass may need this method to
// implement an interface method
stubattribs |= MethodAttributes.Final | MethodAttributes.NewSlot;
}
}
Type[] parameterTypes = mw.GetParametersForDefineMethod();
Type returnType = mw.ReturnTypeForDefineMethod;
// register the name where about to use up (it can't exist already)
if (mw.Name != wrapper.GenerateUniqueMethodName(mw.Name, returnType, parameterTypes))
{
throw new InvalidOperationException();
}
MethodBuilder mb = typeBuilder.DefineMethod(mw.Name, stubattribs, returnType, parameterTypes);
AttributeHelper.HideFromReflection(mb, HideFromReflectionAttribute.Type1aAccessStub);
if (!mw.IsAbstract)
{
CodeEmitter ilgen = CodeEmitter.Create(mb);
Type[] realParamTypes = mw.GetParametersForDefineMethod();
int argpos = 0;
if (!mw.IsStatic)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)argpos++);
}
for (int i = 0; i < realParamTypes.Length; i++)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)argpos++);
}
mw.EmitCall(ilgen);
ilgen.Emit(OpCodes.Ret);
ilgen.DoEmit();
}
}
private void GenerateType1bAccessStub(MethodWrapper mw, bool virt)
private void GenerateAccessStub(int id, MethodWrapper mw, bool virt, bool type1)
{
Debug.Assert(!mw.HasCallerID);
MethodAttributes stubattribs = mw.IsPublic && virt ? MethodAttributes.Public : MethodAttributes.FamORAssem;
@ -4556,30 +4567,43 @@ namespace IKVM.Internal
{
stubattribs |= MethodAttributes.Static;
}
TypeWrapper[] realParameterTypes = mw.GetParameters();
Type[] parameterTypes = new Type[realParameterTypes.Length];
for (int i = 0; i < realParameterTypes.Length; i++)
TypeWrapper[] parameters = mw.GetParameters();
Type[] realParameterTypes = new Type[parameters.Length];
Type[] parameterTypes = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
parameterTypes[i] = realParameterTypes[i].GetPublicBaseTypeWrapper().TypeAsSignatureType;
realParameterTypes[i] = parameters[i].TypeAsSignatureType;
parameterTypes[i] = ToPublicSignatureType(parameters[i]);
}
Type returnType = ToPublicSignatureType(mw.ReturnType);
string name = virt ? wrapper.GenerateUniqueMethodName(mw.Name, returnType, parameterTypes) : NamePrefix.NonVirtual + id;
MethodBuilder mb = typeBuilder.DefineMethod(name, stubattribs, returnType, parameterTypes);
if (virt && type1)
{
AttributeHelper.HideFromReflection(mb);
AttributeHelper.SetNameSig(mb, NamePrefix.AccessStub + id + "|" + mw.Name, mw.Signature);
}
else
{
AttributeHelper.HideFromJava(mb);
if (!type1)
{
AttributeHelper.SetNameSig(mb, mw.Name, mw.Signature);
}
}
Type returnType = mw.ReturnType.GetPublicBaseTypeWrapper().TypeAsSignatureType;
string realName = wrapper.GenerateUniqueMethodName(virt ? mw.Name : NamePrefix.Type1bNonVirtualAccessStub + mw.Name, returnType, parameterTypes);
MethodBuilder mb = typeBuilder.DefineMethod(realName, stubattribs, returnType, parameterTypes);
AttributeHelper.HideFromReflection(mb, mw.IsStatic ? HideFromReflectionAttribute.Type1bAccessStubStatic : virt ? HideFromReflectionAttribute.Type1bAccessStubVirtual : HideFromReflectionAttribute.Type1bAccessStubNonVirtual);
AttributeHelper.SetNameSig(mb, mw.Name, mw.Signature);
CodeEmitter ilgen = CodeEmitter.Create(mb);
Type[] realParamTypes = mw.GetParametersForDefineMethod();
int argpos = 0;
if (!mw.IsStatic)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)argpos++);
}
for (int i = 0; i < realParamTypes.Length; i++)
for (int i = 0; i < parameterTypes.Length; i++)
{
ilgen.Emit(OpCodes.Ldarg_S, (byte)argpos++);
if (realParamTypes[i] != parameterTypes[i])
// we don't need to do a DynamicCast if for unloadables, because the method itself will already do that
if (parameterTypes[i] != realParameterTypes[i])
{
ilgen.Emit(OpCodes.Castclass, realParamTypes[i]);
ilgen.Emit(OpCodes.Castclass, realParameterTypes[i]);
}
}
if (mw.IsStatic || !virt)
@ -4593,6 +4617,23 @@ namespace IKVM.Internal
ilgen.Emit(OpCodes.Ret);
ilgen.DoEmit();
}
private static Type ToPublicSignatureType(TypeWrapper tw)
{
return (tw.IsPublic ? tw : tw.GetPublicBaseTypeWrapper()).TypeAsSignatureType;
}
private bool ParametersAreAccessible(MethodWrapper mw)
{
foreach (TypeWrapper tw in mw.GetParameters())
{
if (!tw.IsAccessibleFrom(wrapper))
{
return false;
}
}
return true;
}
#endif // STATIC_COMPILER
private void ImplementInterfaceMethodStubs(Dictionary<TypeWrapper, TypeWrapper> doneSet, TypeWrapper interfaceTypeWrapper, bool baseClassInterface)

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

@ -1,5 +1,5 @@
/*
Copyright (C) 2002-2009 Jeroen Frijters
Copyright (C) 2002-2011 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -467,7 +467,7 @@ namespace IKVM.Internal
private void UpdateNonPublicTypeInSignatureFlag()
{
if ((IsPublic || IsProtected) && (returnTypeWrapper != null && parameterTypeWrappers != null))
if ((IsPublic || IsProtected) && (returnTypeWrapper != null && parameterTypeWrappers != null) && !(this is AccessStubMethodWrapper))
{
if (!returnTypeWrapper.IsPublic && !returnTypeWrapper.IsUnloadable)
{
@ -1205,11 +1205,13 @@ namespace IKVM.Internal
sealed class AccessStubMethodWrapper : SmartMethodWrapper
{
private readonly MethodInfo stubVirtual;
private readonly MethodInfo stubNonVirtual;
internal AccessStubMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodInfo stubVirtual, MethodInfo stubNonVirtual, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags)
: base(declaringType, name, sig, stubVirtual, returnType, parameterTypes, modifiers, flags)
internal AccessStubMethodWrapper(TypeWrapper declaringType, string name, string sig, MethodInfo core, MethodInfo stubVirtual, MethodInfo stubNonVirtual, TypeWrapper returnType, TypeWrapper[] parameterTypes, Modifiers modifiers, MemberFlags flags)
: base(declaringType, name, sig, core, returnType, parameterTypes, modifiers, flags)
{
this.stubVirtual = stubVirtual;
this.stubNonVirtual = stubNonVirtual;
}
@ -1221,7 +1223,7 @@ namespace IKVM.Internal
protected override void CallvirtImpl(CodeEmitter ilgen)
{
ilgen.Emit(OpCodes.Callvirt, (MethodInfo)GetMethod());
ilgen.Emit(OpCodes.Callvirt, stubVirtual);
}
#endif // !STUB_GENERATOR
}

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

@ -496,37 +496,6 @@ namespace IKVM.Internal
return mi.IsDefined(typeofHideFromReflectionAttribute, false);
}
internal static bool IsHideFromReflection(MemberInfo mi, out int reason)
{
#if !STATIC_COMPILER && !STUB_GENERATOR
object[] attr = mi.GetCustomAttributes(typeof(HideFromReflectionAttribute), false);
if (attr.Length == 1)
{
reason = ((HideFromReflectionAttribute)attr[0]).Reason;
return true;
}
reason = HideFromReflectionAttribute.Unknown;
return false;
#else
IList<CustomAttributeData> attr = CustomAttributeData.__GetCustomAttributes(mi, typeofHideFromReflectionAttribute, false);
if (attr.Count == 1)
{
IList<CustomAttributeTypedArgument> args = attr[0].ConstructorArguments;
if (args.Count == 1)
{
reason = (int)args[0].Value;
}
else
{
reason = HideFromReflectionAttribute.Unknown;
}
return true;
}
reason = HideFromReflectionAttribute.Unknown;
return false;
#endif
}
internal static void HideFromJava(TypeBuilder typeBuilder)
{
if(hideFromJavaAttribute == null)
@ -1686,7 +1655,8 @@ namespace IKVM.Internal
static class NamePrefix
{
internal const string Type2AccessStubBackingField = "__<>";
internal const string Type1bNonVirtualAccessStub = "<nonvirtual>";
internal const string AccessStub = "<accessstub>";
internal const string NonVirtual = "<nonvirtual>";
}
internal abstract class TypeWrapper
@ -3105,6 +3075,7 @@ namespace IKVM.Internal
internal TypeWrapper GetPublicBaseTypeWrapper()
{
Debug.Assert(!this.IsPublic);
if (this.IsUnloadable || this.IsInterface)
{
return CoreClasses.java.lang.Object.Wrapper;
@ -3983,7 +3954,6 @@ namespace IKVM.Internal
{
bool isDelegate = type.BaseType == Types.MulticastDelegate;
List<MethodWrapper> methods = new List<MethodWrapper>();
List<MethodInfo> type1bAccessStubs = null;
const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
foreach(ConstructorInfo ctor in type.GetConstructors(flags))
{
@ -3993,21 +3963,17 @@ namespace IKVM.Internal
}
else
{
AddMethodOrConstructor(ctor, methods, ref type1bAccessStubs);
AddMethodOrConstructor(ctor, methods);
}
}
foreach(MethodInfo method in type.GetMethods(flags))
{
AddMethodOrConstructor(method, methods, ref type1bAccessStubs);
}
if(type1bAccessStubs != null)
{
AddType1bAccessStubs(methods, type1bAccessStubs);
AddMethodOrConstructor(method, methods);
}
SetMethods(methods.ToArray());
}
private void AddMethodOrConstructor(MethodBase method, List<MethodWrapper> methods, ref List<MethodInfo> type1bAccessStubs)
private void AddMethodOrConstructor(MethodBase method, List<MethodWrapper> methods)
{
if(!AttributeHelper.IsHideFromJava(method))
{
@ -4022,85 +3988,62 @@ namespace IKVM.Internal
TypeWrapper retType;
TypeWrapper[] paramTypes;
MethodInfo mi = method as MethodInfo;
int reason = HideFromReflectionAttribute.Unknown;
bool hideFromReflection = mi != null ? AttributeHelper.IsHideFromReflection(mi, out reason) : false;
bool hideFromReflection = mi != null ? AttributeHelper.IsHideFromReflection(mi) : false;
MemberFlags flags = hideFromReflection ? MemberFlags.HideFromReflection : MemberFlags.None;
switch (reason)
{
case HideFromReflectionAttribute.Type1aAccessStub:
case HideFromReflectionAttribute.Type1bAccessStubStatic:
flags |= MemberFlags.AccessStub;
break;
case HideFromReflectionAttribute.Type1bAccessStubVirtual:
case HideFromReflectionAttribute.Type1bAccessStubNonVirtual:
if (type1bAccessStubs == null)
{
type1bAccessStubs = new List<MethodInfo>();
}
type1bAccessStubs.Add(mi);
return;
}
GetNameSigFromMethodBase(method, out name, out sig, out retType, out paramTypes, ref flags);
ExModifiers mods = AttributeHelper.GetModifiers(method, false);
if(mods.IsInternal)
{
flags |= MemberFlags.InternalAccess;
}
methods.Add(MethodWrapper.Create(this, name, sig, method, retType, paramTypes, mods.Modifiers, flags));
if(hideFromReflection && name.StartsWith(NamePrefix.AccessStub, StringComparison.Ordinal))
{
int id = Int32.Parse(name.Substring(NamePrefix.AccessStub.Length, name.IndexOf('|', NamePrefix.AccessStub.Length) - NamePrefix.AccessStub.Length));
name = name.Substring(name.IndexOf('|', NamePrefix.AccessStub.Length) + 1);
flags |= MemberFlags.AccessStub;
MethodInfo nonvirt = type.GetMethod(NamePrefix.NonVirtual + id, BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance);
methods.Add(new AccessStubMethodWrapper(this, name, sig, mi, mi, nonvirt ?? mi, retType, paramTypes, mods.Modifiers & ~Modifiers.Final, flags));
return;
}
MethodWrapper mw = MethodWrapper.Create(this, name, sig, method, retType, paramTypes, mods.Modifiers, flags);
if (mw.HasNonPublicTypeInSignature)
{
MethodInfo stubVirt;
MethodInfo stubNonVirt;
if (GetType2AccessStubs(name, sig, out stubVirt, out stubNonVirt))
{
mw = new AccessStubMethodWrapper(this, name, sig, mi, stubVirt, stubNonVirt ?? stubVirt, retType, paramTypes, mw.Modifiers, flags);
}
}
methods.Add(mw);
}
}
}
private void AddType1bAccessStubs(List<MethodWrapper> methods, List<MethodInfo> type1bAccessStubs)
private bool GetType2AccessStubs(string name, string sig, out MethodInfo stubVirt, out MethodInfo stubNonVirt)
{
for (int i = 0; i < type1bAccessStubs.Count; i++)
stubVirt = null;
stubNonVirt = null;
const BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance;
foreach (MethodInfo method in type.GetMethods(flags))
{
if (type1bAccessStubs[i] != null)
if (AttributeHelper.IsHideFromJava(method))
{
string name1;
string sig1;
TypeWrapper retType1;
TypeWrapper[] paramTypes1;
MemberFlags flags1 = MemberFlags.HideFromReflection;
GetNameSigFromMethodBase(type1bAccessStubs[i], out name1, out sig1, out retType1, out paramTypes1, ref flags1);
MethodInfo found = null;
for (int j = i + 1; j < type1bAccessStubs.Count; j++)
NameSigAttribute attr = AttributeHelper.GetNameSig(method);
if (attr != null && attr.Name == name && attr.Sig == sig)
{
if (type1bAccessStubs[j] != null)
if (method.Name.StartsWith(NamePrefix.NonVirtual, StringComparison.Ordinal))
{
string name2;
string sig2;
TypeWrapper retType2;
TypeWrapper[] paramTypes2;
MemberFlags flags2 = MemberFlags.HideFromReflection | MemberFlags.AccessStub;
GetNameSigFromMethodBase(type1bAccessStubs[j], out name2, out sig2, out retType2, out paramTypes2, ref flags2);
if (name1 == name2 && sig1 == sig2)
{
found = type1bAccessStubs[j];
type1bAccessStubs[j] = null;
break;
}
stubNonVirt = method;
}
else
{
stubVirt = method;
}
}
MethodInfo stubVirtual;
MethodInfo stubNonVirtual;
if (found == null)
{
stubVirtual = stubNonVirtual = type1bAccessStubs[i];
}
else if (found.Name.StartsWith(NamePrefix.Type1bNonVirtualAccessStub, StringComparison.Ordinal))
{
stubVirtual = type1bAccessStubs[i];
stubNonVirtual = found;
}
else
{
stubVirtual = found;
stubNonVirtual = type1bAccessStubs[i];
}
methods.Add(new AccessStubMethodWrapper(this, name1, sig1, stubVirtual, stubNonVirtual, retType1, paramTypes1, stubVirtual.IsPublic ? Modifiers.Public : Modifiers.Protected, MemberFlags.HideFromReflection | MemberFlags.AccessStub));
}
}
return stubVirt != null;
}
private static int SortFieldByToken(FieldInfo field1, FieldInfo field2)

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

@ -423,28 +423,6 @@ namespace IKVM.Attributes
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
public sealed class HideFromReflectionAttribute : Attribute
{
private readonly int reason;
// reasons
public const int Unknown = 0;
public const int Type1aAccessStub = 1;
public const int Type1bAccessStubVirtual = 2;
public const int Type1bAccessStubNonVirtual = 3;
public const int Type1bAccessStubStatic = 4;
public HideFromReflectionAttribute()
: this(Unknown)
{
}
public HideFromReflectionAttribute(int reason)
{
this.reason = reason;
}
public int Reason
{
get { return reason; }
}
}
[Flags]