- .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:
jfrijters 2007-03-29 09:17:19 +00:00
Родитель 0444985b5b
Коммит 0a1a172d3b
6 изменённых файлов: 143 добавлений и 36 удалений

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

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