зеркало из https://github.com/mono/ikvm-fork.git
*** empty log message ***
This commit is contained in:
Родитель
afe6bc0055
Коммит
8bde1e1e49
|
@ -68,7 +68,7 @@ public class ByteCodeHelper
|
||||||
throw JavaException.NegativeArraySizeException();
|
throw JavaException.NegativeArraySizeException();
|
||||||
}
|
}
|
||||||
TypeWrapper wrapper = LoadTypeWrapper(type, clazz);
|
TypeWrapper wrapper = LoadTypeWrapper(type, clazz);
|
||||||
return Array.CreateInstance(wrapper.TypeOrUnloadableAsObject, length);
|
return Array.CreateInstance(wrapper.TypeAsArrayType, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
[StackTraceInfo(Hidden = true)]
|
[StackTraceInfo(Hidden = true)]
|
||||||
|
|
|
@ -132,13 +132,17 @@ class ClassLoaderWrapper
|
||||||
|
|
||||||
internal static bool IsGhost(TypeWrapper wrapper)
|
internal static bool IsGhost(TypeWrapper wrapper)
|
||||||
{
|
{
|
||||||
string name = wrapper.Name;
|
return wrapper.IsInterface && wrapper.GetClassLoader() == bootstrapClassLoader && ghosts.ContainsKey(wrapper.Name);
|
||||||
return wrapper.GetClassLoader() == bootstrapClassLoader && name != null && ghosts.ContainsKey(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static TypeWrapper[] GetGhostImplementers(TypeWrapper wrapper)
|
internal static TypeWrapper[] GetGhostImplementers(TypeWrapper wrapper)
|
||||||
{
|
{
|
||||||
return (TypeWrapper[])((ArrayList)ghosts[wrapper.Name]).ToArray(typeof(TypeWrapper));
|
ArrayList list = (ArrayList)ghosts[wrapper.Name];
|
||||||
|
if(list == null)
|
||||||
|
{
|
||||||
|
return TypeWrapper.EmptyArray;
|
||||||
|
}
|
||||||
|
return (TypeWrapper[])list.ToArray(typeof(TypeWrapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool IsRemappedType(Type type)
|
internal static bool IsRemappedType(Type type)
|
||||||
|
|
|
@ -386,12 +386,12 @@ public abstract class CodeEmitter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CastEmitter : CodeEmitter
|
class ReturnCastEmitter : CodeEmitter
|
||||||
{
|
{
|
||||||
private Type type;
|
private Type type;
|
||||||
private string className;
|
private string className;
|
||||||
|
|
||||||
internal CastEmitter(string className)
|
internal ReturnCastEmitter(string className)
|
||||||
{
|
{
|
||||||
this.className = className;
|
this.className = className;
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,7 @@ class CastEmitter : CodeEmitter
|
||||||
{
|
{
|
||||||
if(type == null)
|
if(type == null)
|
||||||
{
|
{
|
||||||
type = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(className).TypeOrUnloadableAsObject;
|
type = ClassLoaderWrapper.GetBootstrapClassLoader().LoadClassByDottedName(className).TypeAsParameterType;
|
||||||
}
|
}
|
||||||
if(type != typeof(object))
|
if(type != typeof(object))
|
||||||
{
|
{
|
||||||
|
|
|
@ -206,7 +206,7 @@ class MethodWrapper : MemberWrapper
|
||||||
LocalBuilder[] argLocals = new LocalBuilder[args.Length];
|
LocalBuilder[] argLocals = new LocalBuilder[args.Length];
|
||||||
for(int i = args.Length - 1; i >= 0; i--)
|
for(int i = args.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
argLocals[i] = ilgen.DeclareLocal(args[i].TypeOrUnloadableAsObject);
|
argLocals[i] = ilgen.DeclareLocal(args[i].TypeAsLocalOrStackType);
|
||||||
ilgen.Emit(OpCodes.Stloc, argLocals[i]);
|
ilgen.Emit(OpCodes.Stloc, argLocals[i]);
|
||||||
}
|
}
|
||||||
Label end = ilgen.DefineLabel();
|
Label end = ilgen.DefineLabel();
|
||||||
|
|
|
@ -966,8 +966,7 @@ abstract class TypeWrapper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this should really be named TypeAsLocalArgOrStackType (or something like that)
|
internal Type TypeAsFieldType
|
||||||
internal Type TypeOrUnloadableAsObject
|
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -985,11 +984,71 @@ abstract class TypeWrapper
|
||||||
}
|
}
|
||||||
return Type.GetType(type, true);
|
return Type.GetType(type, true);
|
||||||
}
|
}
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Type TypeAsParameterType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return TypeAsFieldType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Type TypeAsBaseType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Type TypeAsLocalOrStackType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
// HACK as a convenience to the compiler, we replace return address types with typeof(int)
|
// HACK as a convenience to the compiler, we replace return address types with typeof(int)
|
||||||
if(VerifierTypeWrapper.IsRet(this))
|
if(VerifierTypeWrapper.IsRet(this))
|
||||||
{
|
{
|
||||||
return typeof(int);
|
return typeof(int);
|
||||||
}
|
}
|
||||||
|
if(IsUnloadable || IsGhost || IsNonPrimitiveValueType)
|
||||||
|
{
|
||||||
|
return typeof(object);
|
||||||
|
}
|
||||||
|
if(IsGhostArray)
|
||||||
|
{
|
||||||
|
int rank = ArrayRank;
|
||||||
|
string type = "System.Object";
|
||||||
|
for(int i = 0; i < rank; i++)
|
||||||
|
{
|
||||||
|
type += "[]";
|
||||||
|
}
|
||||||
|
return Type.GetType(type, true);
|
||||||
|
}
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Type TypeAsArrayType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// TODO if ghosts are ever compiled as value types (for fields), we need special treatment here,
|
||||||
|
// otherwise array covariance breaks down
|
||||||
|
return TypeAsFieldType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Type TypeAsExceptionType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(IsUnloadable)
|
||||||
|
{
|
||||||
|
return typeof(Exception);
|
||||||
|
}
|
||||||
return Type;
|
return Type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1696,12 +1755,12 @@ class DynamicTypeWrapper : TypeWrapper
|
||||||
typeAttribs |= TypeAttributes.Class;
|
typeAttribs |= TypeAttributes.Class;
|
||||||
if(outer != null)
|
if(outer != null)
|
||||||
{
|
{
|
||||||
// TODO in the CLR interfaces cannot contain nested types!
|
// TODO in the CLR interfaces cannot contain nested types! (well, it works fine, but the spec says it isn't allowed)
|
||||||
typeBuilder = outer.DefineNestedType(GetInnerClassName(outerClassWrapper.Name, f.Name), typeAttribs, wrapper.BaseTypeWrapper.Type);
|
typeBuilder = outer.DefineNestedType(GetInnerClassName(outerClassWrapper.Name, f.Name), typeAttribs, wrapper.BaseTypeWrapper.TypeAsBaseType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
typeBuilder = wrapper.GetClassLoader().ModuleBuilder.DefineType(wrapper.GetClassLoader().MangleTypeName(f.Name), typeAttribs, wrapper.BaseTypeWrapper.Type);
|
typeBuilder = wrapper.GetClassLoader().ModuleBuilder.DefineType(wrapper.GetClassLoader().MangleTypeName(f.Name), typeAttribs, wrapper.BaseTypeWrapper.TypeAsBaseType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeWrapper[] interfaces = wrapper.Interfaces;
|
TypeWrapper[] interfaces = wrapper.Interfaces;
|
||||||
|
@ -2105,7 +2164,7 @@ class DynamicTypeWrapper : TypeWrapper
|
||||||
modargs[1] = typeof(IntPtr);
|
modargs[1] = typeof(IntPtr);
|
||||||
for(int i = 0; i < args.Length; i++)
|
for(int i = 0; i < args.Length; i++)
|
||||||
{
|
{
|
||||||
modargs[i + 2] = args[i].TypeOrUnloadableAsObject;
|
modargs[i + 2] = args[i].TypeAsParameterType;
|
||||||
}
|
}
|
||||||
int add = 0;
|
int add = 0;
|
||||||
if(!m.IsStatic)
|
if(!m.IsStatic)
|
||||||
|
@ -2159,7 +2218,7 @@ class DynamicTypeWrapper : TypeWrapper
|
||||||
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.Type);
|
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeOrUnloadableAsObject);
|
retValue = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsParameterType);
|
||||||
ilGenerator.Emit(OpCodes.Stloc, retValue);
|
ilGenerator.Emit(OpCodes.Stloc, retValue);
|
||||||
}
|
}
|
||||||
ilGenerator.BeginCatchBlock(typeof(object));
|
ilGenerator.BeginCatchBlock(typeof(object));
|
||||||
|
@ -2233,12 +2292,15 @@ class DynamicTypeWrapper : TypeWrapper
|
||||||
{
|
{
|
||||||
FieldBuilder field;
|
FieldBuilder field;
|
||||||
ClassFile.Field fld = classFile.Fields[i];
|
ClassFile.Field fld = classFile.Fields[i];
|
||||||
|
string fieldName = fld.Name;
|
||||||
TypeWrapper typeWrapper = fld.GetFieldType(wrapper.GetClassLoader());
|
TypeWrapper typeWrapper = fld.GetFieldType(wrapper.GetClassLoader());
|
||||||
Type type = typeWrapper.TypeOrUnloadableAsObject;
|
Type type = typeWrapper.TypeAsFieldType;
|
||||||
if(typeWrapper.IsUnloadable)
|
if(typeWrapper.IsUnloadable)
|
||||||
{
|
{
|
||||||
// TODO the field name should be mangled here, because otherwise it might conflict with another field
|
// the field name is mangled here, because otherwise it can (theoretically)
|
||||||
// with the same name and a different unloadable type (or java.lang.Object as its type)
|
// conflict with another unloadable or object field
|
||||||
|
// (fields can be overloaded on type)
|
||||||
|
fieldName += "/" + typeWrapper.Name;
|
||||||
}
|
}
|
||||||
FieldAttributes attribs = 0;
|
FieldAttributes attribs = 0;
|
||||||
MethodAttributes methodAttribs = 0;
|
MethodAttributes methodAttribs = 0;
|
||||||
|
@ -2275,7 +2337,7 @@ class DynamicTypeWrapper : TypeWrapper
|
||||||
{
|
{
|
||||||
Profiler.Count("Static Final Constant");
|
Profiler.Count("Static Final Constant");
|
||||||
attribs |= FieldAttributes.Literal;
|
attribs |= FieldAttributes.Literal;
|
||||||
field = typeBuilder.DefineField(fld.Name, type, attribs);
|
field = typeBuilder.DefineField(fieldName, type, attribs);
|
||||||
field.SetConstant(constantValue);
|
field.SetConstant(constantValue);
|
||||||
// NOTE even though you're not supposed to access a constant static final (the compiler is supposed
|
// NOTE even though you're not supposed to access a constant static final (the compiler is supposed
|
||||||
// to inline them), we have to support it (because it does happen, e.g. if the field becomes final
|
// to inline them), we have to support it (because it does happen, e.g. if the field becomes final
|
||||||
|
@ -2301,7 +2363,7 @@ class DynamicTypeWrapper : TypeWrapper
|
||||||
setModifiers = true;
|
setModifiers = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
field = typeBuilder.DefineField(fld.Name, type, attribs);
|
field = typeBuilder.DefineField(fieldName, type, attribs);
|
||||||
if(fld.IsTransient)
|
if(fld.IsTransient)
|
||||||
{
|
{
|
||||||
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(typeof(NonSerializedAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
|
CustomAttributeBuilder transientAttrib = new CustomAttributeBuilder(typeof(NonSerializedAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
|
||||||
|
@ -2419,10 +2481,10 @@ class DynamicTypeWrapper : TypeWrapper
|
||||||
TypeWrapper[] argTypeWrappers = m.GetArgTypes(wrapper.GetClassLoader());
|
TypeWrapper[] argTypeWrappers = m.GetArgTypes(wrapper.GetClassLoader());
|
||||||
TypeWrapper retTypeWrapper = m.GetRetType(wrapper.GetClassLoader());
|
TypeWrapper retTypeWrapper = m.GetRetType(wrapper.GetClassLoader());
|
||||||
Type[] args = new Type[argTypeWrappers.Length];
|
Type[] args = new Type[argTypeWrappers.Length];
|
||||||
Type retType = retTypeWrapper.TypeOrUnloadableAsObject;
|
Type retType = retTypeWrapper.TypeAsParameterType;
|
||||||
for(int i = 0; i < args.Length; i++)
|
for(int i = 0; i < args.Length; i++)
|
||||||
{
|
{
|
||||||
args[i] = argTypeWrappers[i].TypeOrUnloadableAsObject;
|
args[i] = argTypeWrappers[i].TypeAsParameterType;
|
||||||
}
|
}
|
||||||
bool setModifiers = false;
|
bool setModifiers = false;
|
||||||
MethodAttributes attribs = 0;
|
MethodAttributes attribs = 0;
|
||||||
|
@ -2995,7 +3057,7 @@ class RemappedTypeWrapper : TypeWrapper
|
||||||
{
|
{
|
||||||
ret = ret.Substring(1, ret.Length - 2);
|
ret = ret.Substring(1, ret.Length - 2);
|
||||||
}
|
}
|
||||||
retcast = new CastEmitter(ret);
|
retcast = new ReturnCastEmitter(ret);
|
||||||
}
|
}
|
||||||
if(BaseTypeWrapper != null && !Type.IsSealed)
|
if(BaseTypeWrapper != null && !Type.IsSealed)
|
||||||
{
|
{
|
||||||
|
@ -3198,7 +3260,7 @@ class RemappedTypeWrapper : TypeWrapper
|
||||||
{
|
{
|
||||||
ret = ret.Substring(1, ret.Length - 2);
|
ret = ret.Substring(1, ret.Length - 2);
|
||||||
}
|
}
|
||||||
retcast = new CastEmitter(ret);
|
retcast = new ReturnCastEmitter(ret);
|
||||||
}
|
}
|
||||||
CodeEmitter ignore = null;
|
CodeEmitter ignore = null;
|
||||||
MethodWrapper.CreateEmitters(null, redirect, ref ignore, ref ignore, ref newopc);
|
MethodWrapper.CreateEmitters(null, redirect, ref ignore, ref ignore, ref newopc);
|
||||||
|
@ -3276,11 +3338,11 @@ class RemappedTypeWrapper : TypeWrapper
|
||||||
{
|
{
|
||||||
if(fieldSig[0] == 'L')
|
if(fieldSig[0] == 'L')
|
||||||
{
|
{
|
||||||
getter += new CastEmitter(fieldSig.Substring(1, fieldSig.Length - 2));
|
getter += new ReturnCastEmitter(fieldSig.Substring(1, fieldSig.Length - 2));
|
||||||
}
|
}
|
||||||
else if(fieldSig[0] == '[')
|
else if(fieldSig[0] == '[')
|
||||||
{
|
{
|
||||||
getter += new CastEmitter(fieldSig);
|
getter += new ReturnCastEmitter(fieldSig);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3752,7 +3814,15 @@ class CompiledTypeWrapper : TypeWrapper
|
||||||
{
|
{
|
||||||
if(!AttributeHelper.IsHideFromReflection(fields[i]))
|
if(!AttributeHelper.IsHideFromReflection(fields[i]))
|
||||||
{
|
{
|
||||||
list.Add(CreateFieldWrapper(AttributeHelper.GetModifiers(fields[i]), fields[i].Name, fields[i].FieldType, fields[i], null));
|
// if the field name is mangled (because its type is unloadable),
|
||||||
|
// chop off the mangled bit
|
||||||
|
string fieldName = fields[i].Name;
|
||||||
|
int idx = fieldName.IndexOf('/');
|
||||||
|
if(idx >= 0)
|
||||||
|
{
|
||||||
|
fieldName = fieldName.Substring(0, idx);
|
||||||
|
}
|
||||||
|
list.Add(CreateFieldWrapper(AttributeHelper.GetModifiers(fields[i]), fieldName, fields[i].FieldType, fields[i], null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (FieldWrapper[])list.ToArray(typeof(FieldWrapper));
|
return (FieldWrapper[])list.ToArray(typeof(FieldWrapper));
|
||||||
|
|
|
@ -375,13 +375,9 @@ class Compiler
|
||||||
{
|
{
|
||||||
// new objects aren't really there on the stack
|
// new objects aren't really there on the stack
|
||||||
}
|
}
|
||||||
else if(!type.IsUnloadable && type.IsNonPrimitiveValueType)
|
|
||||||
{
|
|
||||||
locals[i] = ilgen.DeclareLocal(typeof(object));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
locals[i] = ilgen.DeclareLocal(type.TypeOrUnloadableAsObject);
|
locals[i] = ilgen.DeclareLocal(type.TypeAsLocalOrStackType);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -556,7 +552,7 @@ class Compiler
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LocalBuilder local = ilGenerator.DeclareLocal(t.TypeOrUnloadableAsObject);
|
LocalBuilder local = ilGenerator.DeclareLocal(t.TypeAsLocalOrStackType);
|
||||||
stack.Push(local);
|
stack.Push(local);
|
||||||
ilGenerator.Emit(OpCodes.Stloc, local);
|
ilGenerator.Emit(OpCodes.Stloc, local);
|
||||||
}
|
}
|
||||||
|
@ -620,7 +616,7 @@ class Compiler
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LocalBuilder local = ilGenerator.DeclareLocal(t.TypeOrUnloadableAsObject);
|
LocalBuilder local = ilGenerator.DeclareLocal(t.TypeAsLocalOrStackType);
|
||||||
bc.Stack.Push(local);
|
bc.Stack.Push(local);
|
||||||
ilGenerator.Emit(OpCodes.Stloc, local);
|
ilGenerator.Emit(OpCodes.Stloc, local);
|
||||||
}
|
}
|
||||||
|
@ -642,7 +638,7 @@ class Compiler
|
||||||
{
|
{
|
||||||
exceptionTypeWrapper = tw;
|
exceptionTypeWrapper = tw;
|
||||||
}
|
}
|
||||||
excType = tw.TypeOrUnloadableAsObject;
|
excType = tw.TypeAsExceptionType;
|
||||||
}
|
}
|
||||||
if(true)
|
if(true)
|
||||||
{
|
{
|
||||||
|
@ -1082,7 +1078,7 @@ class Compiler
|
||||||
}
|
}
|
||||||
else if(!VerifierTypeWrapper.IsNew(stacktype))
|
else if(!VerifierTypeWrapper.IsNew(stacktype))
|
||||||
{
|
{
|
||||||
LocalBuilder lb = ilGenerator.DeclareLocal(stacktype.TypeOrUnloadableAsObject);
|
LocalBuilder lb = ilGenerator.DeclareLocal(stacktype.TypeAsLocalOrStackType);
|
||||||
ilGenerator.Emit(OpCodes.Stloc, lb);
|
ilGenerator.Emit(OpCodes.Stloc, lb);
|
||||||
tempstack[j] = lb;
|
tempstack[j] = lb;
|
||||||
}
|
}
|
||||||
|
@ -1180,7 +1176,7 @@ class Compiler
|
||||||
if(instr.NormalizedOpCode != NormalizedByteCode.__return)
|
if(instr.NormalizedOpCode != NormalizedByteCode.__return)
|
||||||
{
|
{
|
||||||
TypeWrapper retTypeWrapper = m.Method.GetRetType(classLoader);
|
TypeWrapper retTypeWrapper = m.Method.GetRetType(classLoader);
|
||||||
rc.Local = ilGenerator.DeclareLocal(retTypeWrapper.TypeOrUnloadableAsObject);
|
rc.Local = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsLocalOrStackType);
|
||||||
if(!retTypeWrapper.IsUnloadable)
|
if(!retTypeWrapper.IsUnloadable)
|
||||||
{
|
{
|
||||||
// because of the way interface merging works, any reference is valid
|
// because of the way interface merging works, any reference is valid
|
||||||
|
@ -1234,7 +1230,7 @@ class Compiler
|
||||||
}
|
}
|
||||||
if(stackHeight != 1)
|
if(stackHeight != 1)
|
||||||
{
|
{
|
||||||
LocalBuilder local = ilGenerator.DeclareLocal(retTypeWrapper.TypeOrUnloadableAsObject);
|
LocalBuilder local = ilGenerator.DeclareLocal(retTypeWrapper.TypeAsLocalOrStackType);
|
||||||
ilGenerator.Emit(OpCodes.Stloc, local);
|
ilGenerator.Emit(OpCodes.Stloc, local);
|
||||||
for(int j = 1; j < stackHeight; j++)
|
for(int j = 1; j < stackHeight; j++)
|
||||||
{
|
{
|
||||||
|
@ -1384,7 +1380,7 @@ class Compiler
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Type type = wrapper.TypeOrUnloadableAsObject;
|
Type type = wrapper.TypeAsArrayType;
|
||||||
ilGenerator.Emit(OpCodes.Ldtoken, type);
|
ilGenerator.Emit(OpCodes.Ldtoken, type);
|
||||||
ilGenerator.Emit(OpCodes.Ldloc, localArray);
|
ilGenerator.Emit(OpCodes.Ldloc, localArray);
|
||||||
ilGenerator.Emit(OpCodes.Call, multiANewArrayMethod);
|
ilGenerator.Emit(OpCodes.Call, multiANewArrayMethod);
|
||||||
|
@ -1403,7 +1399,7 @@ class Compiler
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// HACK we use TypeOrUnloadableAsObject here, to make sure that Ghost implementers can be
|
// NOTE for ghost types we create object arrays to make sure that Ghost implementers can be
|
||||||
// stored in ghost arrays, but this has the unintended consequence that ghost arrays can
|
// stored in ghost arrays, but this has the unintended consequence that ghost arrays can
|
||||||
// contain *any* reference type (because they are compiled as Object arrays). We could
|
// contain *any* reference type (because they are compiled as Object arrays). We could
|
||||||
// modify aastore to emit code to check for this, but this would have an huge performance
|
// modify aastore to emit code to check for this, but this would have an huge performance
|
||||||
|
@ -1413,7 +1409,7 @@ class Compiler
|
||||||
// is unfortunate, but I think we can live with this minor incompatibility.
|
// is unfortunate, but I think we can live with this minor incompatibility.
|
||||||
// NOTE that this does not break type safety, because when the incorrect object is eventually
|
// NOTE that this does not break type safety, because when the incorrect object is eventually
|
||||||
// used as the ghost interface type it will generate a ClassCastException.
|
// used as the ghost interface type it will generate a ClassCastException.
|
||||||
ilGenerator.Emit(OpCodes.Newarr, wrapper.TypeOrUnloadableAsObject);
|
ilGenerator.Emit(OpCodes.Newarr, wrapper.TypeAsArrayType);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2886,7 +2882,7 @@ class Compiler
|
||||||
TypeWrapper t = ma.GetDeclaredLocalTypeWrapper(index);
|
TypeWrapper t = ma.GetDeclaredLocalTypeWrapper(index);
|
||||||
if(t != VerifierTypeWrapper.Null)
|
if(t != VerifierTypeWrapper.Null)
|
||||||
{
|
{
|
||||||
type = t.TypeOrUnloadableAsObject;
|
type = t.TypeAsLocalOrStackType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalBuilder lb = (LocalBuilder)locals[name];
|
LocalBuilder lb = (LocalBuilder)locals[name];
|
||||||
|
|
Загрузка…
Ссылка в новой задаче