This commit is contained in:
jfrijters 2003-09-10 14:58:19 +00:00
Родитель afe6bc0055
Коммит 8bde1e1e49
6 изменённых файлов: 112 добавлений и 42 удалений

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

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