зеркало из https://github.com/mono/ikvm-fork.git
- .NET "generic class loaders" now return something sensible when toString() is called on them.
- Ikvmc no longer warns about generic stubs. - Ikvmstub now has WHIDBEY conditional code to properly determine if a class is a generic type instance (instead of the name based hack). - Fixed .NET generic type name mangling bug (nested generic types were double encoded). - Added support for loading .NET generic type stubs. - Fixed several .NET generic type loading bugs. - Fixed ikvm.runtime.Util.getInstanceTypeFromClass() to return null instead of throw an exception when it is called on a "dynamic only" class.
This commit is contained in:
Родитель
0444985b5b
Коммит
0a1a172d3b
|
@ -159,6 +159,7 @@ public final class AssemblyClassLoader extends ClassLoader
|
|||
private static native Assembly[] FindResourceAssemblies(Object classLoader, String name, boolean firstOnly);
|
||||
private static native int GetGenericClassLoaderId(AssemblyClassLoader classLoader);
|
||||
private static native Assembly GetBootClassLoaderAssembly();
|
||||
private static native String GetGenericClassLoaderName(Object classLoader);
|
||||
// also used by VMClassLoader
|
||||
public static native String[] GetPackages(Object classLoader);
|
||||
|
||||
|
@ -268,8 +269,7 @@ public final class AssemblyClassLoader extends ClassLoader
|
|||
{
|
||||
return assembly.get_FullName();
|
||||
}
|
||||
// TODO make this string more meaningful
|
||||
return "GenericClassLoader";
|
||||
return GetGenericClassLoaderName(this);
|
||||
}
|
||||
|
||||
private URL getCodeBase()
|
||||
|
|
|
@ -2371,7 +2371,10 @@ namespace IKVM.Internal
|
|||
{
|
||||
if(wrapper.GetClassLoader() != loader)
|
||||
{
|
||||
StaticCompiler.IssueMessage(Message.SkippingReferencedClass, s, ((AssemblyClassLoader)wrapper.GetClassLoader()).Assembly.FullName);
|
||||
if(!(wrapper.GetClassLoader() is GenericClassLoader))
|
||||
{
|
||||
StaticCompiler.IssueMessage(Message.SkippingReferencedClass, s, ((AssemblyClassLoader)wrapper.GetClassLoader()).Assembly.FullName);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(map == null)
|
||||
|
|
|
@ -221,8 +221,18 @@ public class NetExp
|
|||
|
||||
private static bool IsGenericType(java.lang.Class c)
|
||||
{
|
||||
// HACK huge hack, we look for the backtick
|
||||
#if WHIDBEY
|
||||
Type t = ikvm.runtime.Util.getInstanceTypeFromClass(c);
|
||||
while(t == null && c.getDeclaringClass() != null)
|
||||
{
|
||||
// dynamic only inner class, so we look at the declaring class
|
||||
c = c.getDeclaringClass();
|
||||
t = ikvm.runtime.Util.getInstanceTypeFromClass(c);
|
||||
}
|
||||
return t.IsGenericType;
|
||||
#else
|
||||
return c.getName().IndexOf("$$0060") > 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void ProcessClass(java.lang.Class c)
|
||||
|
|
|
@ -223,25 +223,22 @@ namespace IKVM.Internal
|
|||
string dotnetAssembly = f.IKVMAssemblyAttribute;
|
||||
if(dotnetAssembly != null)
|
||||
{
|
||||
// The sole purpose of the stub class is to let us load the assembly that the class lives in,
|
||||
// once we've done that, all types in it become visible.
|
||||
Assembly asm;
|
||||
// It's a stub class generated by ikvmstub (or generated by the runtime when getResource was
|
||||
// called on a statically compiled class).
|
||||
ClassLoaderWrapper loader;
|
||||
try
|
||||
{
|
||||
#if WHIDBEY && STATIC_COMPILER
|
||||
asm = Assembly.ReflectionOnlyLoad(dotnetAssembly);
|
||||
#else
|
||||
asm = Assembly.Load(dotnetAssembly);
|
||||
#endif
|
||||
loader = ClassLoaderWrapper.GetAssemblyClassLoaderByName(dotnetAssembly);
|
||||
}
|
||||
catch(Exception x)
|
||||
{
|
||||
// TODO don't catch all exceptions here
|
||||
throw new NoClassDefFoundError(f.Name + " (" + x.Message + ")");
|
||||
}
|
||||
TypeWrapper tw = ClassLoaderWrapper.GetAssemblyClassLoader(asm).LoadClassByDottedNameFast(f.Name);
|
||||
TypeWrapper tw = loader.LoadClassByDottedNameFast(f.Name);
|
||||
if(tw == null)
|
||||
{
|
||||
throw new NoClassDefFoundError(f.Name + " (type not found in " + asm.FullName + ")");
|
||||
throw new NoClassDefFoundError(f.Name + " (type not found in " + dotnetAssembly + ")");
|
||||
}
|
||||
return RegisterInitiatingLoader(tw);
|
||||
}
|
||||
|
@ -465,7 +462,7 @@ namespace IKVM.Internal
|
|||
{
|
||||
return null;
|
||||
}
|
||||
Type type = GetBootstrapClassLoader().GetType(DotNetTypeWrapper.DemangleTypeName(name.Substring(0, pos)));
|
||||
Type type = GetType(DotNetTypeWrapper.DemangleTypeName(name.Substring(0, pos)));
|
||||
if(type == null || !Whidbey.IsGenericTypeDefinition(type))
|
||||
{
|
||||
return null;
|
||||
|
@ -518,8 +515,13 @@ namespace IKVM.Internal
|
|||
for(int i = 0; i < typeArguments.Length; i++)
|
||||
{
|
||||
string s = (string)typeParamNames[i];
|
||||
s = s.Replace("__", ".");
|
||||
s = s.Replace("$$005F$$005F", "__");
|
||||
// only do the unmangling for non-generic types (because we don't want to convert
|
||||
// the double underscores in two adjacent _$$$_ or _$$$$_ markers)
|
||||
if(s.IndexOf("_$$$_") == -1)
|
||||
{
|
||||
s = s.Replace("__", ".");
|
||||
s = s.Replace("$$005F$$005F", "__");
|
||||
}
|
||||
int dims = 0;
|
||||
while(s.Length > dims && s[dims] == 'A')
|
||||
{
|
||||
|
@ -874,7 +876,13 @@ namespace IKVM.Internal
|
|||
}
|
||||
}
|
||||
ClassLoaderWrapper[] key = (ClassLoaderWrapper[])list.ToArray(typeof(ClassLoaderWrapper));
|
||||
ClassLoaderWrapper matchingLoader = null;
|
||||
ClassLoaderWrapper matchingLoader = GetGenericClassLoaderByKey(key);
|
||||
matchingLoader.RegisterInitiatingLoader(wrapper);
|
||||
return matchingLoader;
|
||||
}
|
||||
|
||||
private static ClassLoaderWrapper GetGenericClassLoaderByKey(ClassLoaderWrapper[] key)
|
||||
{
|
||||
lock(wrapperLock)
|
||||
{
|
||||
if(genericClassLoaders == null)
|
||||
|
@ -885,25 +893,76 @@ namespace IKVM.Internal
|
|||
{
|
||||
if(loader.Matches(key))
|
||||
{
|
||||
matchingLoader = loader;
|
||||
break;
|
||||
return loader;
|
||||
}
|
||||
}
|
||||
if(matchingLoader == null)
|
||||
object javaClassLoader = null;
|
||||
#if !STATIC_COMPILER
|
||||
javaClassLoader = JVM.Library.newAssemblyClassLoader(null);
|
||||
#endif
|
||||
GenericClassLoader newLoader = new GenericClassLoader(key, javaClassLoader);
|
||||
#if !STATIC_COMPILER
|
||||
JVM.Library.setWrapperForClassLoader(javaClassLoader, newLoader);
|
||||
#endif
|
||||
genericClassLoaders.Add(newLoader);
|
||||
return newLoader;
|
||||
}
|
||||
}
|
||||
|
||||
internal static ClassLoaderWrapper GetGenericClassLoaderByName(string name)
|
||||
{
|
||||
Debug.Assert(name.StartsWith("[[") && name.EndsWith("]]"));
|
||||
Stack stack = new Stack();
|
||||
ArrayList list = null;
|
||||
for(int i = 0; i < name.Length; i++)
|
||||
{
|
||||
if(name[i] == '[')
|
||||
{
|
||||
object javaClassLoader = null;
|
||||
#if !STATIC_COMPILER
|
||||
javaClassLoader = JVM.Library.newAssemblyClassLoader(null);
|
||||
#endif
|
||||
matchingLoader = new GenericClassLoader(key, javaClassLoader);
|
||||
#if !STATIC_COMPILER
|
||||
JVM.Library.setWrapperForClassLoader(javaClassLoader, matchingLoader);
|
||||
#endif
|
||||
genericClassLoaders.Add(matchingLoader);
|
||||
if(name[i + 1] == '[')
|
||||
{
|
||||
stack.Push(list);
|
||||
list = new ArrayList();
|
||||
if(name[i + 2] == '[')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int start = i + 1;
|
||||
i = name.IndexOf(']', i);
|
||||
list.Add(ClassLoaderWrapper.GetAssemblyClassLoaderByName(name.Substring(start, i - start)));
|
||||
}
|
||||
}
|
||||
else if(name[i] == ']')
|
||||
{
|
||||
ClassLoaderWrapper loader = GetGenericClassLoaderByKey((ClassLoaderWrapper[])list.ToArray(typeof(ClassLoaderWrapper)));
|
||||
list = (ArrayList)stack.Pop();
|
||||
if(list == null)
|
||||
{
|
||||
return loader;
|
||||
}
|
||||
list.Add(loader);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
matchingLoader.RegisterInitiatingLoader(wrapper);
|
||||
return matchingLoader;
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
internal static ClassLoaderWrapper GetAssemblyClassLoaderByName(string name)
|
||||
{
|
||||
if(name.StartsWith("[["))
|
||||
{
|
||||
return GetGenericClassLoaderByName(name);
|
||||
}
|
||||
#if WHIDBEY && STATIC_COMPILER
|
||||
return ClassLoaderWrapper.GetAssemblyClassLoader(Assembly.ReflectionOnlyLoad(name));
|
||||
#else
|
||||
return ClassLoaderWrapper.GetAssemblyClassLoader(Assembly.Load(name));
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static int GetGenericClassLoaderId(ClassLoaderWrapper wrapper)
|
||||
|
@ -1067,6 +1126,28 @@ namespace IKVM.Internal
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal string GetName()
|
||||
{
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
sb.Append('[');
|
||||
foreach(ClassLoaderWrapper loader in delegates)
|
||||
{
|
||||
sb.Append('[');
|
||||
GenericClassLoader gcl = loader as GenericClassLoader;
|
||||
if(gcl != null)
|
||||
{
|
||||
sb.Append(gcl.GetName());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(((AssemblyClassLoader)loader).Assembly.FullName);
|
||||
}
|
||||
sb.Append(']');
|
||||
}
|
||||
sb.Append(']');
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
class AssemblyClassLoader : ClassLoaderWrapper
|
||||
|
|
|
@ -8706,8 +8706,13 @@ namespace IKVM.Internal
|
|||
else
|
||||
{
|
||||
string s = tw.Name;
|
||||
s = s.Replace("__", "$$005F$$005F");
|
||||
s = s.Replace(".", "__");
|
||||
// only do the mangling for non-generic types (because we don't want to convert
|
||||
// the double underscores in two adjacent _$$$_ or _$$$$_ markers)
|
||||
if (s.IndexOf("_$$$_") == -1)
|
||||
{
|
||||
s = s.Replace("__", "$$005F$$005F");
|
||||
s = s.Replace(".", "__");
|
||||
}
|
||||
sb.Append('L').Append(s);
|
||||
}
|
||||
sep = "_$$_";
|
||||
|
|
|
@ -1583,6 +1583,11 @@ namespace IKVM.NativeCode.ikvm.@internal
|
|||
{
|
||||
return ((IKVM.Internal.AssemblyClassLoader)ClassLoaderWrapper.GetBootstrapClassLoader()).Assembly;
|
||||
}
|
||||
|
||||
public static string GetGenericClassLoaderName(object classLoader)
|
||||
{
|
||||
return ((GenericClassLoader)JVM.Library.getWrapperFromClassLoader(classLoader)).GetName();
|
||||
}
|
||||
}
|
||||
|
||||
namespace stubgen
|
||||
|
@ -1599,8 +1604,7 @@ namespace IKVM.NativeCode.ikvm.@internal
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
return "TODO: implement support for generic types referencing multiple assemblies in their IKVM.NET.Assembly attribute";
|
||||
return ((IKVM.Internal.GenericClassLoader)loader).GetName();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1717,6 +1721,10 @@ namespace IKVM.NativeCode.ikvm.runtime
|
|||
public static Type GetInstanceTypeFromTypeWrapper(object wrapperObject)
|
||||
{
|
||||
TypeWrapper wrapper = (TypeWrapper)wrapperObject;
|
||||
if(wrapper.IsDynamicOnly)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if(wrapper.IsRemapped && wrapper.IsFinal)
|
||||
{
|
||||
return wrapper.TypeAsTBD;
|
||||
|
|
Загрузка…
Ссылка в новой задаче