зеркало из https://github.com/mono/ikvm-fork.git
no message
This commit is contained in:
Родитель
eef60b5726
Коммит
98df8c2fbe
|
@ -49,9 +49,10 @@ class ClassFile
|
|||
{
|
||||
private ConstantPoolItem[] constantpool;
|
||||
private Modifiers access_flags;
|
||||
private string name;
|
||||
private string supername;
|
||||
private string[] interfaces;
|
||||
private ConstantPoolItemClass this_cpi;
|
||||
private ConstantPoolItemClass super_cpi;
|
||||
private ConstantPoolItemClass[] interfaces;
|
||||
private TypeWrapper[] interfaceTypeWrappers;
|
||||
private Field[] fields;
|
||||
private Method[] methods;
|
||||
private Attribute[] attributes;
|
||||
|
@ -114,7 +115,7 @@ class ClassFile
|
|||
int this_class = br.ReadUInt16();
|
||||
try
|
||||
{
|
||||
name = ((ConstantPoolItemClass)constantpool[this_class]).Name;
|
||||
this_cpi = (ConstantPoolItemClass)constantpool[this_class];
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
|
@ -127,7 +128,7 @@ class ClassFile
|
|||
{
|
||||
try
|
||||
{
|
||||
supername = ((ConstantPoolItemClass)constantpool[super_class]).Name;
|
||||
super_cpi = (ConstantPoolItemClass)constantpool[super_class];
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
|
@ -141,12 +142,12 @@ class ClassFile
|
|||
throw JavaException.ClassFormatError("{0} (Bad superclass index)", Name);
|
||||
}
|
||||
}
|
||||
if(IsInterface && (super_class == 0 || supername != "java/lang/Object"))
|
||||
if(IsInterface && (super_class == 0 || super_cpi.Name != "java/lang/Object"))
|
||||
{
|
||||
throw JavaException.ClassFormatError("{0} (Interfaces must have java.lang.Object as superclass)", Name);
|
||||
}
|
||||
int interfaces_count = br.ReadUInt16();
|
||||
interfaces = new string[interfaces_count];
|
||||
interfaces = new ConstantPoolItemClass[interfaces_count];
|
||||
Hashtable interfaceNames = new Hashtable();
|
||||
for(int i = 0; i < interfaces_count; i++)
|
||||
{
|
||||
|
@ -160,7 +161,7 @@ class ClassFile
|
|||
{
|
||||
throw JavaException.ClassFormatError("{0} (Interface name has bad constant type)", Name);
|
||||
}
|
||||
interfaces[i] = ((ConstantPoolItemClass)GetConstantPoolItem(index)).Name;
|
||||
interfaces[i] = (ConstantPoolItemClass)GetConstantPoolItem(index);
|
||||
if(interfaceNames.ContainsKey(interfaces[i]))
|
||||
{
|
||||
throw JavaException.ClassFormatError("{0} (Repetitive interface name)", Name);
|
||||
|
@ -321,6 +322,11 @@ class ClassFile
|
|||
return ((ConstantPoolItemClass)constantpool[index]).Name;
|
||||
}
|
||||
|
||||
internal TypeWrapper GetConstantPoolClassType(int index, ClassLoaderWrapper classLoader)
|
||||
{
|
||||
return ((ConstantPoolItemClass)constantpool[index]).GetClassType(classLoader);
|
||||
}
|
||||
|
||||
private string GetConstantPoolString(int index)
|
||||
{
|
||||
return ((ConstantPoolItemString)constantpool[index]).Value;
|
||||
|
@ -364,7 +370,7 @@ class ClassFile
|
|||
{
|
||||
get
|
||||
{
|
||||
return name;
|
||||
return this_cpi.Name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,6 +378,7 @@ class ClassFile
|
|||
{
|
||||
get
|
||||
{
|
||||
string name = Name;
|
||||
int index = name.LastIndexOf('/');
|
||||
if(index == -1)
|
||||
{
|
||||
|
@ -381,11 +388,16 @@ class ClassFile
|
|||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper GetSuperTypeWrapper(ClassLoaderWrapper classLoader)
|
||||
{
|
||||
return super_cpi.GetClassType(classLoader);
|
||||
}
|
||||
|
||||
internal string SuperClass
|
||||
{
|
||||
get
|
||||
{
|
||||
return supername;
|
||||
return super_cpi.Name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,11 +417,31 @@ class ClassFile
|
|||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper[] GetInterfaceTypeWrappers(ClassLoaderWrapper classLoader)
|
||||
{
|
||||
if(interfaceTypeWrappers == null)
|
||||
{
|
||||
TypeWrapper[] tw = new TypeWrapper[interfaces.Length];
|
||||
for(int i = 0; i < tw.Length; i++)
|
||||
{
|
||||
tw[i] = interfaces[i].GetClassType(classLoader);
|
||||
}
|
||||
interfaceTypeWrappers = tw;
|
||||
}
|
||||
return interfaceTypeWrappers;
|
||||
}
|
||||
|
||||
// TODO this is legacy and needs to be removed in the future
|
||||
internal string[] Interfaces
|
||||
{
|
||||
get
|
||||
{
|
||||
return interfaces;
|
||||
string[] s = new string[interfaces.Length];
|
||||
for(int i = 0; i < s.Length; i++)
|
||||
{
|
||||
s[i] = interfaces[i].Name;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -539,12 +571,113 @@ class ClassFile
|
|||
{
|
||||
if(typeWrapper == null)
|
||||
{
|
||||
typeWrapper = classLoader.LoadClassBySlashedName(name);
|
||||
typeWrapper = LoadClassHelper(classLoader, name);
|
||||
}
|
||||
return typeWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
private static TypeWrapper LoadClassHelper(ClassLoaderWrapper classLoader, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return classLoader.LoadClassBySlashedName(name);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
// TODO consider what to do with this error, may be a command line switch?
|
||||
// TODO it might not be a good idea to catch .NET system exceptions here
|
||||
return new UnloadableTypeWrapper(name);
|
||||
}
|
||||
}
|
||||
|
||||
private static TypeWrapper SigDecoderWrapper(ClassLoaderWrapper classLoader, ref int index, string sig)
|
||||
{
|
||||
switch(sig[index++])
|
||||
{
|
||||
case 'B':
|
||||
return PrimitiveTypeWrapper.BYTE;
|
||||
case 'C':
|
||||
return PrimitiveTypeWrapper.CHAR;
|
||||
case 'D':
|
||||
return PrimitiveTypeWrapper.DOUBLE;
|
||||
case 'F':
|
||||
return PrimitiveTypeWrapper.FLOAT;
|
||||
case 'I':
|
||||
return PrimitiveTypeWrapper.INT;
|
||||
case 'J':
|
||||
return PrimitiveTypeWrapper.LONG;
|
||||
case 'L':
|
||||
{
|
||||
int pos = index;
|
||||
index = sig.IndexOf(';', index) + 1;
|
||||
return LoadClassHelper(classLoader, sig.Substring(pos, index - pos - 1));
|
||||
}
|
||||
case 'S':
|
||||
return PrimitiveTypeWrapper.SHORT;
|
||||
case 'Z':
|
||||
return PrimitiveTypeWrapper.BOOLEAN;
|
||||
case 'V':
|
||||
return PrimitiveTypeWrapper.VOID;
|
||||
case '[':
|
||||
{
|
||||
// TODO this can be optimized
|
||||
string array = "[";
|
||||
while(sig[index] == '[')
|
||||
{
|
||||
index++;
|
||||
array += "[";
|
||||
}
|
||||
switch(sig[index])
|
||||
{
|
||||
case 'L':
|
||||
{
|
||||
int pos = index;
|
||||
index = sig.IndexOf(';', index) + 1;
|
||||
return LoadClassHelper(classLoader, array + sig.Substring(pos, index - pos));
|
||||
}
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'F':
|
||||
case 'I':
|
||||
case 'J':
|
||||
case 'S':
|
||||
case 'Z':
|
||||
return LoadClassHelper(classLoader, array + sig[index++]);
|
||||
default:
|
||||
// TODO this should never happen, because ClassFile should validate the descriptors
|
||||
throw new InvalidOperationException(sig.Substring(index));
|
||||
}
|
||||
}
|
||||
default:
|
||||
// TODO this should never happen, because ClassFile should validate the descriptors
|
||||
throw new InvalidOperationException(sig.Substring(index));
|
||||
}
|
||||
}
|
||||
|
||||
private static TypeWrapper[] ArgTypeWrapperListFromSig(ClassLoaderWrapper classLoader, string sig)
|
||||
{
|
||||
if(sig[1] == ')')
|
||||
{
|
||||
return new TypeWrapper[0];
|
||||
}
|
||||
ArrayList list = new ArrayList();
|
||||
for(int i = 1; sig[i] != ')';)
|
||||
{
|
||||
list.Add(SigDecoderWrapper(classLoader, ref i, sig));
|
||||
}
|
||||
TypeWrapper[] types = new TypeWrapper[list.Count];
|
||||
list.CopyTo(types);
|
||||
return types;
|
||||
}
|
||||
|
||||
private static TypeWrapper RetTypeWrapperFromSig(ClassLoaderWrapper classLoader, string sig)
|
||||
{
|
||||
int index = sig.IndexOf(')') + 1;
|
||||
return SigDecoderWrapper(classLoader, ref index, sig);
|
||||
}
|
||||
|
||||
private class ConstantPoolItemDouble : ConstantPoolItem
|
||||
{
|
||||
private double d;
|
||||
|
@ -628,6 +761,11 @@ class ClassFile
|
|||
{
|
||||
return name_and_type.GetRetType(classLoader);
|
||||
}
|
||||
|
||||
internal TypeWrapper GetFieldType(ClassLoaderWrapper classLoader)
|
||||
{
|
||||
return name_and_type.GetFieldType(classLoader);
|
||||
}
|
||||
}
|
||||
|
||||
internal class ConstantPoolItemFieldref : ConstantPoolItemFMI
|
||||
|
@ -772,7 +910,7 @@ class ClassFile
|
|||
{
|
||||
if(argTypeWrappers == null)
|
||||
{
|
||||
argTypeWrappers = classLoader.ArgTypeWrapperListFromSig(descriptor);
|
||||
argTypeWrappers = ArgTypeWrapperListFromSig(classLoader, descriptor);
|
||||
}
|
||||
return argTypeWrappers;
|
||||
}
|
||||
|
@ -781,7 +919,7 @@ class ClassFile
|
|||
{
|
||||
if(retTypeWrapper == null)
|
||||
{
|
||||
retTypeWrapper = classLoader.RetTypeWrapperFromSig(descriptor);
|
||||
retTypeWrapper = RetTypeWrapperFromSig(classLoader, descriptor);
|
||||
}
|
||||
return retTypeWrapper;
|
||||
}
|
||||
|
@ -790,7 +928,8 @@ class ClassFile
|
|||
{
|
||||
if(fieldTypeWrapper == null)
|
||||
{
|
||||
fieldTypeWrapper = classLoader.RetTypeWrapperFromSig("()" + descriptor);
|
||||
// HACK
|
||||
fieldTypeWrapper = RetTypeWrapperFromSig(classLoader, "()" + descriptor);
|
||||
}
|
||||
return fieldTypeWrapper;
|
||||
}
|
||||
|
@ -920,6 +1059,9 @@ class ClassFile
|
|||
private ushort name_index;
|
||||
private ushort descriptor_index;
|
||||
private Attribute[] attributes;
|
||||
private TypeWrapper[] argTypeWrappers;
|
||||
private TypeWrapper retTypeWrapper;
|
||||
private TypeWrapper fieldTypeWrapper;
|
||||
|
||||
internal FieldOrMethod(ClassFile classFile, BigEndianBinaryReader br)
|
||||
{
|
||||
|
@ -953,6 +1095,34 @@ class ClassFile
|
|||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper[] GetArgTypes(ClassLoaderWrapper classLoader)
|
||||
{
|
||||
if(argTypeWrappers == null)
|
||||
{
|
||||
argTypeWrappers = ArgTypeWrapperListFromSig(classLoader, Signature);
|
||||
}
|
||||
return argTypeWrappers;
|
||||
}
|
||||
|
||||
internal TypeWrapper GetRetType(ClassLoaderWrapper classLoader)
|
||||
{
|
||||
if(retTypeWrapper == null)
|
||||
{
|
||||
retTypeWrapper = RetTypeWrapperFromSig(classLoader, Signature);
|
||||
}
|
||||
return retTypeWrapper;
|
||||
}
|
||||
|
||||
internal TypeWrapper GetFieldType(ClassLoaderWrapper classLoader)
|
||||
{
|
||||
if(fieldTypeWrapper == null)
|
||||
{
|
||||
// HACK
|
||||
fieldTypeWrapper = RetTypeWrapperFromSig(classLoader, "()" + Signature);
|
||||
}
|
||||
return fieldTypeWrapper;
|
||||
}
|
||||
|
||||
internal Modifiers Modifiers
|
||||
{
|
||||
get
|
||||
|
|
|
@ -128,9 +128,9 @@ class ClassLoaderWrapper
|
|||
{
|
||||
nativeMethods = new Hashtable();
|
||||
// TODO interfaces have java/lang/Object as the base type (do they really?)
|
||||
types["java.lang.Cloneable"] = new RemappedTypeWrapper(ModifiersAttribute.GetModifiers(typeof(java.lang.Cloneable)), "java/lang/Cloneable", typeof(java.lang.Cloneable), new TypeWrapper[0], null);
|
||||
types["java.lang.Cloneable"] = new RemappedTypeWrapper(this, ModifiersAttribute.GetModifiers(typeof(java.lang.Cloneable)), "java/lang/Cloneable", typeof(java.lang.Cloneable), new TypeWrapper[0], null);
|
||||
typeToTypeWrapper.Add(typeof(java.lang.Cloneable), types["java.lang.Cloneable"]);
|
||||
types["java.io.Serializable"] = new RemappedTypeWrapper(ModifiersAttribute.GetModifiers(typeof(java.io.Serializable)), "java/io/Serializable", typeof(java.io.Serializable), new TypeWrapper[0], null);
|
||||
types["java.io.Serializable"] = new RemappedTypeWrapper(this, ModifiersAttribute.GetModifiers(typeof(java.io.Serializable)), "java/io/Serializable", typeof(java.io.Serializable), new TypeWrapper[0], null);
|
||||
typeToTypeWrapper.Add(typeof(java.io.Serializable), types["java.io.Serializable"]);
|
||||
MapXml.Root map = null;
|
||||
using(Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream("map.xml"))
|
||||
|
@ -151,7 +151,7 @@ class ClassLoaderWrapper
|
|||
string name = c.Name;
|
||||
Modifiers modifiers = (Modifiers)c.Modifiers;
|
||||
// TODO specify interfaces
|
||||
TypeWrapper tw = new RemappedTypeWrapper(modifiers, name.Replace('.', '/'), Type.GetType(c.Type, true), new TypeWrapper[0], baseWrapper);
|
||||
TypeWrapper tw = new RemappedTypeWrapper(this, modifiers, name.Replace('.', '/'), Type.GetType(c.Type, true), new TypeWrapper[0], baseWrapper);
|
||||
types.Add(name, tw);
|
||||
typeToTypeWrapper.Add(tw.Type, tw);
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ class ClassLoaderWrapper
|
|||
MethodDescriptor mdClone = new MethodDescriptor(GetBootstrapClassLoader(), "clone", "()Ljava/lang/Object;");
|
||||
Modifiers modifiers = Modifiers.Final | Modifiers.Public;
|
||||
// TODO copy accessibility from element type
|
||||
wrapper = new RemappedTypeWrapper(modifiers, name, array, interfaces, GetBootstrapClassLoader().LoadClassByDottedName("java.lang.Object"));
|
||||
wrapper = new RemappedTypeWrapper(this, modifiers, name, array, interfaces, GetBootstrapClassLoader().LoadClassByDottedName("java.lang.Object"));
|
||||
MethodInfo clone = typeof(Array).GetMethod("Clone");
|
||||
MethodWrapper mw = new MethodWrapper(wrapper, mdClone, clone, Modifiers.Public);
|
||||
mw.EmitCall = CodeEmitter.Create(OpCodes.Callvirt, clone);
|
||||
|
@ -415,7 +415,7 @@ class ClassLoaderWrapper
|
|||
}
|
||||
else
|
||||
{
|
||||
type = new DynamicTypeWrapper(f.Name, f, baseType, this, nativeMethods);
|
||||
type = new DynamicTypeWrapper(f, this, nativeMethods);
|
||||
dynamicTypes.Add(f.Name.Replace('/', '.'), type);
|
||||
}
|
||||
types.Add(f.Name.Replace('/', '.'), type);
|
||||
|
@ -526,19 +526,18 @@ class ClassLoaderWrapper
|
|||
return moduleBuilder;
|
||||
}
|
||||
|
||||
internal Type ExpressionType(string type)
|
||||
internal TypeWrapper ExpressionTypeWrapper(string type)
|
||||
{
|
||||
// HACK to ease the burden of the compiler, we support the Lret pseudo type here
|
||||
if(type.StartsWith("Lret;"))
|
||||
{
|
||||
return typeof(int);
|
||||
throw new InvalidOperationException("ExpressionTypeWrapper for Lret; requested");
|
||||
}
|
||||
if(type == "Lnull")
|
||||
{
|
||||
throw new InvalidOperationException("ExpressionType for Lnull requested");
|
||||
throw new InvalidOperationException("ExpressionTypeWrapper for Lnull requested");
|
||||
}
|
||||
int index = 0;
|
||||
return SigDecoder(ref index, type);
|
||||
return SigDecoderWrapper(ref index, type);
|
||||
}
|
||||
|
||||
// NOTE: this will ignore anything following the sig marker (so that it can be used to decode method signatures)
|
||||
|
@ -713,66 +712,6 @@ class ClassLoaderWrapper
|
|||
return types;
|
||||
}
|
||||
|
||||
// subType and baseType are Java class name (e.g. java/lang/Object)
|
||||
internal bool IsSubType(string subType, string baseType)
|
||||
{
|
||||
return LoadClassBySlashedName(subType).IsSubTypeOf(LoadClassBySlashedName(baseType));
|
||||
}
|
||||
|
||||
internal string FindCommonBaseType(string type1, string type2)
|
||||
{
|
||||
TypeWrapper t1 = LoadClassBySlashedName(type1);
|
||||
TypeWrapper t2 = LoadClassBySlashedName(type2);
|
||||
if(t1 == t2)
|
||||
{
|
||||
return type1;
|
||||
}
|
||||
if(t1.IsInterface || t2.IsInterface)
|
||||
{
|
||||
// TODO I don't know how finding the common base for interfaces is defined, but
|
||||
// for now I'm just doing the naive thing
|
||||
// UPDATE according to a paper by Alessandro Coglio & Allen Goldberg titled
|
||||
// "Type Safety in the JVM: Some Problems in Java 2 SDK 1.2 and Proposed Solutions"
|
||||
// the common base of two interfaces is java/lang/Object, and there is special
|
||||
// treatment for java/lang/Object types that allow it to be assigned to any interface
|
||||
// type, the JVM's typesafety then depends on the invokeinterface instruction to make
|
||||
// sure that the reference actually implements the interface.
|
||||
// So strictly speaking, the code below isn't correct, but it works, so for now it stays in.
|
||||
if(t1.ImplementsInterface(t2))
|
||||
{
|
||||
return t2.Name;
|
||||
}
|
||||
if(t2.ImplementsInterface(t1))
|
||||
{
|
||||
return t1.Name;
|
||||
}
|
||||
return "java/lang/Object";
|
||||
}
|
||||
Stack st1 = new Stack();
|
||||
Stack st2 = new Stack();
|
||||
while(t1 != null)
|
||||
{
|
||||
st1.Push(t1);
|
||||
t1 = t1.BaseTypeWrapper;
|
||||
}
|
||||
while(t2 != null)
|
||||
{
|
||||
st2.Push(t2);
|
||||
t2 = t2.BaseTypeWrapper;
|
||||
}
|
||||
TypeWrapper type = null;
|
||||
for(;;)
|
||||
{
|
||||
t1 = st1.Count > 0 ? (TypeWrapper)st1.Pop() : null;
|
||||
t2 = st2.Count > 0 ? (TypeWrapper)st2.Pop() : null;
|
||||
if(t1 != t2)
|
||||
{
|
||||
return type.Name;
|
||||
}
|
||||
type = t1;
|
||||
}
|
||||
}
|
||||
|
||||
internal static ClassLoaderWrapper GetBootstrapClassLoader()
|
||||
{
|
||||
if(bootstrapClassLoader == null)
|
||||
|
@ -821,7 +760,26 @@ class ClassLoaderWrapper
|
|||
internal static TypeWrapper GetWrapperFromTypeFast(Type type)
|
||||
{
|
||||
Debug.Assert(!(type is TypeBuilder));
|
||||
return (TypeWrapper)typeToTypeWrapper[type];
|
||||
TypeWrapper wrapper = (TypeWrapper)typeToTypeWrapper[type];
|
||||
if(wrapper == null && type.IsArray)
|
||||
{
|
||||
// it might be an array of a dynamically compiled Java type
|
||||
int rank = 1;
|
||||
Type elem = type.GetElementType();
|
||||
while(elem.IsArray)
|
||||
{
|
||||
rank++;
|
||||
elem = elem.GetElementType();
|
||||
}
|
||||
wrapper = (TypeWrapper)typeToTypeWrapper[elem];
|
||||
if(wrapper != null)
|
||||
{
|
||||
// HACK this is a lame way of creating the array wrapper
|
||||
wrapper = wrapper.GetClassLoader().LoadClassBySlashedName(new String('[', rank) + "L" + wrapper.Name + ";");
|
||||
typeToTypeWrapper[type] = wrapper;
|
||||
}
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
internal static TypeWrapper GetWrapperFromType(Type type)
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE;PROFILE"
|
||||
DefineConstants = "DEBUG;TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
|
|
|
@ -34,6 +34,22 @@ sealed class MethodDescriptor
|
|||
private string sig;
|
||||
private Type[] args;
|
||||
private Type ret;
|
||||
private TypeWrapper[] argTypeWrappers;
|
||||
private TypeWrapper retTypeWrapper;
|
||||
|
||||
internal MethodDescriptor(ClassLoaderWrapper classLoader, ClassFile.ConstantPoolItemFMI cpi)
|
||||
: this(classLoader, cpi.Name, cpi.Signature)
|
||||
{
|
||||
argTypeWrappers = cpi.GetArgTypes(classLoader);
|
||||
retTypeWrapper = cpi.GetRetType(classLoader);
|
||||
}
|
||||
|
||||
internal MethodDescriptor(ClassLoaderWrapper classLoader, ClassFile.Method method)
|
||||
: this(classLoader, method.Name, method.Signature)
|
||||
{
|
||||
argTypeWrappers = method.GetArgTypes(classLoader);
|
||||
retTypeWrapper = method.GetRetType(classLoader);
|
||||
}
|
||||
|
||||
internal MethodDescriptor(ClassLoaderWrapper classLoader, string name, string sig)
|
||||
{
|
||||
|
@ -76,6 +92,18 @@ sealed class MethodDescriptor
|
|||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper[] ArgTypeWrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
if(argTypeWrappers == null)
|
||||
{
|
||||
argTypeWrappers = classLoader.ArgTypeWrapperListFromSig(sig);
|
||||
}
|
||||
return argTypeWrappers;
|
||||
}
|
||||
}
|
||||
|
||||
internal Type RetType
|
||||
{
|
||||
get
|
||||
|
@ -88,6 +116,18 @@ sealed class MethodDescriptor
|
|||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper RetTypeWrapper
|
||||
{
|
||||
get
|
||||
{
|
||||
if(retTypeWrapper == null)
|
||||
{
|
||||
retTypeWrapper = classLoader.RetTypeWrapperFromSig(sig);
|
||||
}
|
||||
return retTypeWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
// TODO instead of comparing the signature strings, we should compare the actual types
|
||||
|
@ -196,6 +236,51 @@ abstract class TypeWrapper
|
|||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return GetType().Name + "[" + name + "]";
|
||||
}
|
||||
|
||||
// NOTE for non-array types this returns 0
|
||||
internal int ArrayRank
|
||||
{
|
||||
get
|
||||
{
|
||||
int i = 0;
|
||||
while(name[i] == '[')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual bool IsPrimitive
|
||||
{
|
||||
get
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsUnloadable
|
||||
{
|
||||
get
|
||||
{
|
||||
// NOTE we abuse modifiers to note unloadable classes
|
||||
return modifiers == Modifiers.Synthetic;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsVerifierType
|
||||
{
|
||||
get
|
||||
{
|
||||
// NOTE we abuse modifiers to note verifier types
|
||||
return modifiers == (Modifiers.Final | Modifiers.Interface);
|
||||
}
|
||||
}
|
||||
|
||||
internal Modifiers Modifiers
|
||||
{
|
||||
get
|
||||
|
@ -235,6 +320,7 @@ abstract class TypeWrapper
|
|||
|
||||
protected abstract FieldWrapper GetFieldImpl(string fieldName);
|
||||
|
||||
// TODO this shouldn't just be based on the name, fields can be overloaded on type
|
||||
public FieldWrapper GetFieldWrapper(string fieldName)
|
||||
{
|
||||
FieldWrapper fae = (FieldWrapper)fields[fieldName];
|
||||
|
@ -364,6 +450,23 @@ abstract class TypeWrapper
|
|||
get;
|
||||
}
|
||||
|
||||
internal Type TypeOrUnloadableAsObject
|
||||
{
|
||||
get
|
||||
{
|
||||
if(IsUnloadable)
|
||||
{
|
||||
return typeof(object);
|
||||
}
|
||||
// HACK as a convenience to the compiler, we replace return address types with typeof(int)
|
||||
if(VerifierTypeWrapper.IsRet(this))
|
||||
{
|
||||
return typeof(int);
|
||||
}
|
||||
return Type;
|
||||
}
|
||||
}
|
||||
|
||||
public TypeWrapper BaseTypeWrapper
|
||||
{
|
||||
get
|
||||
|
@ -372,6 +475,43 @@ abstract class TypeWrapper
|
|||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper ElementTypeWrapper
|
||||
{
|
||||
get
|
||||
{
|
||||
if(name[0] != '[')
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
// TODO consider caching the element type
|
||||
switch(name[1])
|
||||
{
|
||||
case '[':
|
||||
return classLoader.LoadClassBySlashedName(name.Substring(1));
|
||||
case 'L':
|
||||
return classLoader.LoadClassBySlashedName(name.Substring(2, name.Length - 3));
|
||||
case 'Z':
|
||||
return PrimitiveTypeWrapper.BOOLEAN;
|
||||
case 'B':
|
||||
return PrimitiveTypeWrapper.BYTE;
|
||||
case 'S':
|
||||
return PrimitiveTypeWrapper.SHORT;
|
||||
case 'C':
|
||||
return PrimitiveTypeWrapper.CHAR;
|
||||
case 'I':
|
||||
return PrimitiveTypeWrapper.INT;
|
||||
case 'J':
|
||||
return PrimitiveTypeWrapper.LONG;
|
||||
case 'F':
|
||||
return PrimitiveTypeWrapper.FLOAT;
|
||||
case 'D':
|
||||
return PrimitiveTypeWrapper.DOUBLE;
|
||||
default:
|
||||
throw new InvalidOperationException(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ImplementsInterface(TypeWrapper interfaceWrapper)
|
||||
{
|
||||
TypeWrapper typeWrapper = this;
|
||||
|
@ -415,6 +555,40 @@ abstract class TypeWrapper
|
|||
return true;
|
||||
}
|
||||
|
||||
internal bool IsAssignableTo(TypeWrapper wrapper)
|
||||
{
|
||||
if(this == wrapper)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(wrapper.IsPrimitive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(this == VerifierTypeWrapper.Null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
int rank1 = this.ArrayRank;
|
||||
int rank2 = wrapper.ArrayRank;
|
||||
if(rank1 > 0 && rank2 > 0)
|
||||
{
|
||||
rank1--;
|
||||
rank2--;
|
||||
TypeWrapper elem1 = this.ElementTypeWrapper;
|
||||
TypeWrapper elem2 = wrapper.ElementTypeWrapper;
|
||||
while(rank1 != 0 && rank2 != 0)
|
||||
{
|
||||
elem1 = elem1.ElementTypeWrapper;
|
||||
elem2 = elem2.ElementTypeWrapper;
|
||||
rank1--;
|
||||
rank2--;
|
||||
}
|
||||
return elem1.IsSubTypeOf(elem2);
|
||||
}
|
||||
return this.IsSubTypeOf(wrapper);
|
||||
}
|
||||
|
||||
public abstract bool IsInterface
|
||||
{
|
||||
get;
|
||||
|
@ -608,6 +782,53 @@ abstract class TypeWrapper
|
|||
}
|
||||
}
|
||||
|
||||
class UnloadableTypeWrapper : TypeWrapper
|
||||
{
|
||||
internal UnloadableTypeWrapper(string name)
|
||||
: base(Modifiers.Synthetic, name, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
protected override FieldWrapper GetFieldImpl(string fieldName)
|
||||
{
|
||||
throw new InvalidOperationException("GetFieldImpl called on UnloadableTypeWrapper");
|
||||
}
|
||||
|
||||
protected override MethodWrapper GetMethodImpl(MethodDescriptor md)
|
||||
{
|
||||
throw new InvalidOperationException("GetMethodImpl called on UnloadableTypeWrapper");
|
||||
}
|
||||
|
||||
public override Type Type
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new InvalidOperationException("get_Type called on UnloadableTypeWrapper");
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsInterface
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new InvalidOperationException("get_IsInterface called on UnloadableTypeWrapper");
|
||||
}
|
||||
}
|
||||
|
||||
public override TypeWrapper[] Interfaces
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new InvalidOperationException("get_Interfaces called on UnloadableTypeWrapper");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Finish()
|
||||
{
|
||||
throw new InvalidOperationException("Finish called on UnloadableTypeWrapper");
|
||||
}
|
||||
}
|
||||
|
||||
class PrimitiveTypeWrapper : TypeWrapper
|
||||
{
|
||||
internal static readonly PrimitiveTypeWrapper BYTE = new PrimitiveTypeWrapper(typeof(sbyte));
|
||||
|
@ -628,6 +849,14 @@ class PrimitiveTypeWrapper : TypeWrapper
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
internal override bool IsPrimitive
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override Type Type
|
||||
{
|
||||
get
|
||||
|
@ -673,12 +902,47 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
private DynamicImpl impl;
|
||||
private TypeWrapper[] interfaces;
|
||||
|
||||
internal DynamicTypeWrapper(string name, ClassFile f, TypeWrapper baseType, ClassLoaderWrapper classLoader, Hashtable nativeMethods)
|
||||
: base(f.Modifiers, name, baseType, classLoader)
|
||||
internal DynamicTypeWrapper(ClassFile f, ClassLoaderWrapper classLoader, Hashtable nativeMethods)
|
||||
: base(f.Modifiers, f.Name, f.GetSuperTypeWrapper(classLoader), classLoader)
|
||||
{
|
||||
JavaTypeImpl impl = new JavaTypeImpl(f, this, baseType, nativeMethods);
|
||||
this.impl = impl;
|
||||
interfaces = impl.GetInterfaces();
|
||||
if(BaseTypeWrapper.IsUnloadable)
|
||||
{
|
||||
throw JavaException.NoClassDefFoundError(BaseTypeWrapper.Name);
|
||||
}
|
||||
// if the base type isn't public, it must be in the same package
|
||||
if(!BaseTypeWrapper.IsPublic)
|
||||
{
|
||||
if(BaseTypeWrapper.GetClassLoader() != classLoader || f.PackageName != BaseTypeWrapper.PackageName)
|
||||
{
|
||||
throw JavaException.IllegalAccessError("Class {0} cannot access its superclass {1}", f.Name, BaseTypeWrapper.Name);
|
||||
}
|
||||
}
|
||||
if(BaseTypeWrapper.IsFinal)
|
||||
{
|
||||
throw JavaException.VerifyError("Cannot inherit from final class");
|
||||
}
|
||||
if(BaseTypeWrapper.IsInterface)
|
||||
{
|
||||
throw JavaException.IncompatibleClassChangeError("Class {0} has interface {1} as superclass", f.Name, BaseTypeWrapper.Name);
|
||||
}
|
||||
interfaces = f.GetInterfaceTypeWrappers(classLoader);
|
||||
for(int i = 0; i < interfaces.Length; i++)
|
||||
{
|
||||
if(interfaces[i].IsUnloadable)
|
||||
{
|
||||
throw JavaException.NoClassDefFoundError(interfaces[i].Name);
|
||||
}
|
||||
if(!interfaces[i].IsInterface)
|
||||
{
|
||||
throw JavaException.IncompatibleClassChangeError("Implementing class");
|
||||
}
|
||||
if(!interfaces[i].IsAccessibleFrom(this))
|
||||
{
|
||||
throw JavaException.IllegalAccessError("Class {0} cannot access its superinterface {1}", f.Name, interfaces[i].Name);
|
||||
}
|
||||
}
|
||||
|
||||
impl = new JavaTypeImpl(f, this, BaseTypeWrapper, interfaces, nativeMethods);
|
||||
}
|
||||
|
||||
protected override FieldWrapper GetFieldImpl(string fieldName)
|
||||
|
@ -747,12 +1011,13 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
private FinishedTypeImpl finishedType;
|
||||
private Hashtable nativeMethods;
|
||||
|
||||
internal JavaTypeImpl(ClassFile f, DynamicTypeWrapper wrapper, TypeWrapper baseWrapper, Hashtable nativeMethods)
|
||||
internal JavaTypeImpl(ClassFile f, DynamicTypeWrapper wrapper, TypeWrapper baseWrapper, TypeWrapper[] interfaces, Hashtable nativeMethods)
|
||||
{
|
||||
// Console.WriteLine("constructing JavaTypeImpl for " + f.Name);
|
||||
//Console.WriteLine("constructing JavaTypeImpl for " + f.Name);
|
||||
this.classFile = f;
|
||||
this.wrapper = wrapper;
|
||||
this.baseWrapper = baseWrapper;
|
||||
this.interfaces = interfaces;
|
||||
this.nativeMethods = nativeMethods;
|
||||
|
||||
TypeAttributes typeAttribs = 0;
|
||||
|
@ -768,21 +1033,6 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
{
|
||||
typeAttribs |= TypeAttributes.Public;
|
||||
}
|
||||
interfaces = new TypeWrapper[f.Interfaces.Length];
|
||||
for(int i = 0; i < f.Interfaces.Length; i++)
|
||||
{
|
||||
interfaces[i] = wrapper.GetClassLoader().LoadClassBySlashedName(f.Interfaces[i]);
|
||||
if(!interfaces[i].IsInterface)
|
||||
{
|
||||
throw JavaException.IncompatibleClassChangeError("Implementing class");
|
||||
}
|
||||
if(!interfaces[i].IsAccessibleFrom(wrapper))
|
||||
{
|
||||
throw JavaException.IllegalAccessError("Class {0} cannot access its superinterface {1}", wrapper.Name, interfaces[i].Name);
|
||||
}
|
||||
}
|
||||
// NOTE we call DefineType after all the interfaces have been resolved, because otherwise
|
||||
// we end up with a .NET type that cannot be completed
|
||||
if(f.IsInterface)
|
||||
{
|
||||
typeAttribs |= TypeAttributes.Interface | TypeAttributes.Abstract;
|
||||
|
@ -799,11 +1049,6 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper[] GetInterfaces()
|
||||
{
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
public override DynamicImpl Finish()
|
||||
{
|
||||
if(baseWrapper != null)
|
||||
|
@ -850,7 +1095,7 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
MethodDescriptor[] methodDescriptors = new MethodDescriptor[classFile.Methods.Length];
|
||||
for(int i = 0; i < classFile.Methods.Length; i++)
|
||||
{
|
||||
methodDescriptors[i] = new MethodDescriptor(wrapper.GetClassLoader(), classFile.Methods[i].Name, classFile.Methods[i].Signature);
|
||||
methodDescriptors[i] = new MethodDescriptor(wrapper.GetClassLoader(), classFile.Methods[i]);
|
||||
}
|
||||
if(methodLookup == null)
|
||||
{
|
||||
|
@ -1149,21 +1394,17 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
{
|
||||
FieldBuilder field;
|
||||
ClassFile.Field fld = classFile.Fields[i];
|
||||
Type type = null;
|
||||
try
|
||||
TypeWrapper typeWrapper = fld.GetFieldType(wrapper.GetClassLoader());
|
||||
Type type;
|
||||
if(typeWrapper.IsUnloadable)
|
||||
{
|
||||
type = wrapper.GetClassLoader().ExpressionType(fld.Signature);
|
||||
// TODO the field name should be mangled here, because otherwise it might conflict with another field
|
||||
// with the same name and a different unloadable type (or java.lang.Object as its type)
|
||||
type = typeof(object);
|
||||
}
|
||||
catch(Exception x)
|
||||
else
|
||||
{
|
||||
if(x.GetType().FullName == "java.lang.ClassNotFoundException")
|
||||
{
|
||||
// TODO set fields[i] to a special FieldWrapper that does the appropriate thing (whatever that may be)
|
||||
fields[i] = new FieldWrapper(this.wrapper, fld.Name, fld.Signature, fld.Modifiers);
|
||||
Console.Error.WriteLine("Type " + fld.Signature + " of field " + fld.Name + " in class " + classFile.Name + " is unloadable");
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
type = typeWrapper.Type;
|
||||
}
|
||||
FieldAttributes attribs = 0;
|
||||
MethodAttributes methodAttribs = 0;
|
||||
|
@ -1294,6 +1535,11 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
fields[i] = FieldWrapper.Create(wrapper, field, fld.Signature, fld.Modifiers);
|
||||
}
|
||||
}
|
||||
if(typeWrapper.IsUnloadable)
|
||||
{
|
||||
CustomAttributeBuilder attrib = new CustomAttributeBuilder(typeof(UnloadableTypeAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { typeWrapper.Name });
|
||||
field.SetCustomAttribute(attrib);
|
||||
}
|
||||
// if the Java modifiers cannot be expressed in .NET, we emit the Modifiers attribute to store
|
||||
// the Java modifiers
|
||||
if(setModifiers)
|
||||
|
@ -1310,7 +1556,7 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
methodLookup = new Hashtable();
|
||||
for(int i = 0; i < classFile.Methods.Length; i++)
|
||||
{
|
||||
methodLookup[new MethodDescriptor(wrapper.GetClassLoader(), classFile.Methods[i].Name, classFile.Methods[i].Signature)] = i;
|
||||
methodLookup[new MethodDescriptor(wrapper.GetClassLoader(), classFile.Methods[i])] = i;
|
||||
}
|
||||
}
|
||||
object index = methodLookup[md];
|
||||
|
@ -1332,25 +1578,36 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
// TODO things to consider when we support unloadable types on the argument list on return type:
|
||||
// - later on, the method can be overriden by a class that does have access to the type, so
|
||||
// this should be detected and an appropriate override stub should be generated
|
||||
// - overloading might conflict with the generalised argument list (unloadable types appear
|
||||
// as System.Object). The nicest way to solve this would be to emit a modreq attribute on the parameter,
|
||||
// but Reflection.Emit doesn't support this, so we'll probably have to use a name mangling scheme
|
||||
MethodBase method;
|
||||
ClassFile.Method m = classFile.Methods[index];
|
||||
Type[] args = null;
|
||||
Type retType = null;
|
||||
try
|
||||
TypeWrapper[] argTypeWrappers = m.GetArgTypes(wrapper.GetClassLoader());
|
||||
TypeWrapper retTypeWrapper = m.GetRetType(wrapper.GetClassLoader());
|
||||
Type[] args = new Type[argTypeWrappers.Length];
|
||||
Type retType;
|
||||
if(retTypeWrapper.IsUnloadable)
|
||||
{
|
||||
args = wrapper.GetClassLoader().ArgTypeListFromSig(m.Signature);
|
||||
retType = wrapper.GetClassLoader().RetTypeFromSig(m.Signature);
|
||||
retType = typeof(object);
|
||||
}
|
||||
catch(Exception x)
|
||||
else
|
||||
{
|
||||
if(x.GetType().FullName == "java.lang.ClassNotFoundException")
|
||||
retType = retTypeWrapper.Type;
|
||||
}
|
||||
for(int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if(argTypeWrappers[i].IsUnloadable)
|
||||
{
|
||||
// TODO set methods[i] to a special MethodWrapper that does the appropriate thing (whatever that may be)
|
||||
methods[index] = new MethodWrapper(this.wrapper, new MethodDescriptor(wrapper.GetClassLoader(), m.Name, m.Signature), null, m.Modifiers);
|
||||
Console.Error.WriteLine("Type " + x.Message + " of method " + m.Name + m.Signature + " in class " + classFile.Name + " is unloadable");
|
||||
return;
|
||||
args[i] = typeof(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
args[i] = argTypeWrappers[i].Type;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
MethodAttributes attribs = 0;
|
||||
if(m.IsAbstract)
|
||||
|
@ -1412,7 +1669,7 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
attribs |= MethodAttributes.Virtual;
|
||||
}
|
||||
string name = m.Name;
|
||||
MethodDescriptor md = new MethodDescriptor(wrapper.GetClassLoader(), name, m.Signature);
|
||||
MethodDescriptor md = new MethodDescriptor(wrapper.GetClassLoader(), m);
|
||||
// if a method is virtual, we need to find the method it overrides (if any), for several reasons:
|
||||
// - if we're overriding a method that has a different name (e.g. some of the virtual methods
|
||||
// in System.Object [Equals <-> equals]) we need to add an explicit MethodOverride
|
||||
|
@ -1506,7 +1763,27 @@ class DynamicTypeWrapper : TypeWrapper
|
|||
typeBuilder.DefineMethodOverride(mb, (MethodInfo)baseMethod);
|
||||
}
|
||||
}
|
||||
methods[index] = MethodWrapper.Create(wrapper, new MethodDescriptor(wrapper.GetClassLoader(), m.Name, m.Signature), method, method, m.Modifiers);
|
||||
if(retTypeWrapper.IsUnloadable)
|
||||
{
|
||||
CustomAttributeBuilder attrib = new CustomAttributeBuilder(typeof(UnloadableTypeAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { retTypeWrapper.Name });
|
||||
((MethodBuilder)method).DefineParameter(0, ParameterAttributes.None, null).SetCustomAttribute(attrib);
|
||||
}
|
||||
for(int i = 0; i < argTypeWrappers.Length; i++)
|
||||
{
|
||||
if(argTypeWrappers[i].IsUnloadable)
|
||||
{
|
||||
CustomAttributeBuilder attrib = new CustomAttributeBuilder(typeof(UnloadableTypeAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { argTypeWrappers[i].Name });
|
||||
if(method is MethodBuilder)
|
||||
{
|
||||
((MethodBuilder)method).DefineParameter(i + 1, ParameterAttributes.None, null).SetCustomAttribute(attrib);
|
||||
}
|
||||
else
|
||||
{
|
||||
((ConstructorBuilder)method).DefineParameter(i + 1, ParameterAttributes.None, null).SetCustomAttribute(attrib);
|
||||
}
|
||||
}
|
||||
}
|
||||
methods[index] = MethodWrapper.Create(wrapper, new MethodDescriptor(wrapper.GetClassLoader(), m), method, method, m.Modifiers);
|
||||
}
|
||||
|
||||
public override Type Type
|
||||
|
@ -1568,8 +1845,8 @@ class RemappedTypeWrapper : TypeWrapper
|
|||
private Type virtualsInterface;
|
||||
private Type virtualsHelperHack;
|
||||
|
||||
public RemappedTypeWrapper(Modifiers modifiers, string name, Type type, TypeWrapper[] interfaces, TypeWrapper baseType)
|
||||
: base(modifiers, name, baseType, ClassLoaderWrapper.GetBootstrapClassLoader())
|
||||
public RemappedTypeWrapper(ClassLoaderWrapper classLoader, Modifiers modifiers, string name, Type type, TypeWrapper[] interfaces, TypeWrapper baseType)
|
||||
: base(modifiers, name, baseType, classLoader)
|
||||
{
|
||||
this.type = type;
|
||||
this.interfaces = interfaces;
|
||||
|
@ -1709,9 +1986,8 @@ class RemappedTypeWrapper : TypeWrapper
|
|||
{
|
||||
if(method.@override != null)
|
||||
{
|
||||
MethodDescriptor redir = new MethodDescriptor(GetClassLoader(), method.@override.Name, sig);
|
||||
BindingFlags binding = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
overrideMethod = type.GetMethod(redir.Name, binding, null, CallingConventions.Standard, redir.ArgTypes, null);
|
||||
overrideMethod = type.GetMethod(method.@override.Name, binding, null, CallingConventions.Standard, GetClassLoader().ArgTypeListFromSig(sig), null);
|
||||
if(overrideMethod == null)
|
||||
{
|
||||
throw new InvalidOperationException("Override method not found: " + Name + "." + name + sig);
|
||||
|
@ -2908,13 +3184,13 @@ sealed class MethodWrapper
|
|||
{
|
||||
get
|
||||
{
|
||||
return declaringType.GetClassLoader().RetTypeWrapperFromSig(md.Signature);
|
||||
return md.RetTypeWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper[] GetParameters()
|
||||
{
|
||||
return declaringType.GetClassLoader().ArgTypeWrapperListFromSig(md.Signature);
|
||||
return md.ArgTypeWrappers;
|
||||
}
|
||||
|
||||
internal Modifiers Modifiers
|
||||
|
@ -3139,7 +3415,16 @@ sealed class FieldWrapper
|
|||
{
|
||||
get
|
||||
{
|
||||
return declaringType.GetClassLoader().ExpressionType(sig);
|
||||
return FieldTypeWrapper.Type;
|
||||
}
|
||||
}
|
||||
|
||||
internal TypeWrapper FieldTypeWrapper
|
||||
{
|
||||
get
|
||||
{
|
||||
// HACK
|
||||
return declaringType.GetClassLoader().RetTypeWrapperFromSig("()" + sig);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,25 @@ public class IKVMAssemblyAttribute : Attribute
|
|||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue)]
|
||||
public class UnloadableTypeAttribute : Attribute
|
||||
{
|
||||
private string name;
|
||||
|
||||
public UnloadableTypeAttribute(string name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All)]
|
||||
public class ModifiersAttribute : Attribute
|
||||
{
|
||||
|
|
|
@ -1100,7 +1100,25 @@ namespace NativeCode.java
|
|||
}
|
||||
// we need to finish the type otherwise all methods will not be in the method map yet
|
||||
wrapper.Finish();
|
||||
return wrapper.GetMethods();
|
||||
// we need to look through the array for unloadable types, because we may not let them
|
||||
// escape into the 'wild'
|
||||
MethodWrapper[] methods = wrapper.GetMethods();
|
||||
for(int i = 0; i < methods.Length; i++)
|
||||
{
|
||||
if(methods[i].ReturnType.IsUnloadable)
|
||||
{
|
||||
throw JavaException.NoClassDefFoundError(methods[i].ReturnType.Name);
|
||||
}
|
||||
TypeWrapper[] args = methods[i].GetParameters();
|
||||
for(int j = 0; j < args.Length; j++)
|
||||
{
|
||||
if(args[j].IsUnloadable)
|
||||
{
|
||||
throw JavaException.NoClassDefFoundError(args[j].Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
public static object[] GetDeclaredFields(Type type, object cwrapper)
|
||||
|
@ -1112,7 +1130,17 @@ namespace NativeCode.java
|
|||
}
|
||||
// we need to finish the type otherwise all fields will not be in the field map yet
|
||||
wrapper.Finish();
|
||||
return wrapper.GetFields();
|
||||
// we need to look through the array for unloadable types, because we may not let them
|
||||
// escape into the 'wild'
|
||||
FieldWrapper[] fields = wrapper.GetFields();
|
||||
for(int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
if(fields[i].FieldTypeWrapper.IsUnloadable)
|
||||
{
|
||||
throw JavaException.NoClassDefFoundError(fields[i].FieldTypeWrapper.Name);
|
||||
}
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
public static object[] GetDeclaredClasses(Type type, object cwrapper)
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -37,7 +37,7 @@ public final class FileDescriptor
|
|||
{
|
||||
}
|
||||
|
||||
private FileDescriptor(Stream stream)
|
||||
public FileDescriptor(Stream stream)
|
||||
{
|
||||
this.stream = stream;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче