This commit is contained in:
jfrijters 2005-12-29 09:57:41 +00:00
Родитель a2b54470a6
Коммит 7cc7744ec9
3 изменённых файлов: 114 добавлений и 31 удалений

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

@ -637,6 +637,7 @@ class Compiler
{
Null,
New,
This,
UnitializedThis,
Other
}
@ -681,6 +682,10 @@ class Compiler
// new objects aren't really there on the stack
types[i] = StackType.New;
}
else if(VerifierTypeWrapper.IsThis(type))
{
types[i] = StackType.This;
}
else if(type == VerifierTypeWrapper.UninitializedThis)
{
// uninitialized references cannot be stored in a local, but we can reload them
@ -703,6 +708,7 @@ class Compiler
case StackType.New:
// new objects aren't really there on the stack
break;
case StackType.This:
case StackType.UnitializedThis:
compiler.ilGenerator.Emit(OpCodes.Ldarg_0);
break;
@ -719,6 +725,7 @@ class Compiler
switch(types[i])
{
case StackType.Null:
case StackType.This:
case StackType.UnitializedThis:
compiler.ilGenerator.Emit(OpCodes.Pop);
break;
@ -1417,8 +1424,7 @@ class Compiler
ClassFile.ConstantPoolItemFieldref cpi = classFile.GetFieldref(instr.Arg1);
FieldWrapper field = cpi.GetField();
TypeWrapper tw = field.FieldTypeWrapper;
TypeWrapper val = ma.GetRawStackTypeWrapper(i, 0);
tw.EmitConvStackTypeToSignatureType(ilGenerator, val);
tw.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0));
field.EmitSet(ilGenerator);
break;
}
@ -1511,8 +1517,8 @@ class Compiler
cpi.Signature == "(Ljava.lang.Object;ILjava.lang.Object;II)V" &&
cpi.GetClassType().GetClassLoader() == ClassLoaderWrapper.GetBootstrapClassLoader())
{
TypeWrapper dst_type = ma.GetRawStackTypeWrapper(i, 2);
TypeWrapper src_type = ma.GetRawStackTypeWrapper(i, 4);
TypeWrapper dst_type = ma.GetStackTypeWrapper(i, 2);
TypeWrapper src_type = ma.GetStackTypeWrapper(i, 4);
if(!dst_type.IsUnloadable && dst_type.IsArray && dst_type == src_type)
{
switch(dst_type.Name[1])
@ -1675,7 +1681,7 @@ class Compiler
{
if(!stackfix[j])
{
TypeWrapper stacktype = ma.GetRawStackTypeWrapper(i, argcount + 1 + j);
TypeWrapper stacktype = ma.GetStackTypeWrapper(i, argcount + 1 + j);
// it could be another new object reference (not from current invokespecial <init>
// instruction)
if(stacktype == VerifierTypeWrapper.Null)
@ -1763,10 +1769,21 @@ class Compiler
}
else
{
if(instr.NormalizedOpCode == NormalizedByteCode.__invokespecial
&& !method.IsPrivate) // if the method is private, we can get away with a callvirt (and not generate the stub)
if(instr.NormalizedOpCode == NormalizedByteCode.__invokespecial)
{
ilGenerator.Emit(OpCodes.Callvirt, GetInvokeSpecialStub(method));
if(VerifierTypeWrapper.IsThis(type))
{
method.EmitCall(ilGenerator);
}
else if(method.IsPrivate)
{
// if the method is private, we can get away with a callvirt (and not generate the stub)
method.EmitCallvirt(ilGenerator);
}
else
{
ilGenerator.Emit(OpCodes.Callvirt, GetInvokeSpecialStub(method));
}
}
else
{
@ -1793,11 +1810,7 @@ class Compiler
if(instr.NormalizedOpCode != NormalizedByteCode.__return)
{
TypeWrapper retTypeWrapper = mw.ReturnType;
retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0));
if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable)
{
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsSignatureType);
}
retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0));
local = UnsafeAllocTempLocal(retTypeWrapper.TypeAsSignatureType);
ilGenerator.Emit(OpCodes.Stloc, local);
}
@ -1822,11 +1835,7 @@ class Compiler
else
{
TypeWrapper retTypeWrapper = mw.ReturnType;
retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetRawStackTypeWrapper(i, 0));
if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable)
{
ilGenerator.Emit(OpCodes.Castclass, retTypeWrapper.TypeAsSignatureType);
}
retTypeWrapper.EmitConvStackTypeToSignatureType(ilGenerator, ma.GetStackTypeWrapper(i, 0));
if(stackHeight != 1)
{
LocalBuilder local = AllocTempLocal(retTypeWrapper.TypeAsSignatureType);
@ -1852,6 +1861,10 @@ class Compiler
{
// since new objects aren't represented on the stack, we don't need to do anything here
}
else if(VerifierTypeWrapper.IsThis(type))
{
ilGenerator.Emit(OpCodes.Ldarg_0);
}
else if(type == VerifierTypeWrapper.UninitializedThis)
{
// any unitialized this reference has to be loaded from arg 0
@ -2982,7 +2995,7 @@ class Compiler
}
else if(args[i].IsInterfaceOrInterfaceArray)
{
TypeWrapper tw = ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i);
TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i);
if(!tw.IsUnloadable && !tw.IsAssignableTo(args[i]))
{
needsCast = true;
@ -3020,7 +3033,8 @@ class Compiler
for(int i = firstCastArg + 1; i < args.Length; i++)
{
TypeWrapper tw = ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i);
if(tw != VerifierTypeWrapper.UninitializedThis)
if(tw != VerifierTypeWrapper.UninitializedThis
&& !VerifierTypeWrapper.IsThis(tw))
{
tw = args[i];
}
@ -3030,7 +3044,7 @@ class Compiler
{
if(!args[i].IsUnloadable && !args[i].IsGhost)
{
TypeWrapper tw = ma.GetRawStackTypeWrapper(instructionIndex, args.Length - 1 - i);
TypeWrapper tw = ma.GetStackTypeWrapper(instructionIndex, args.Length - 1 - i);
if(tw.IsUnloadable || (args[i].IsInterfaceOrInterfaceArray && !tw.IsAssignableTo(args[i])))
{
EmitHelper.EmitAssertType(ilGenerator, args[i].TypeAsTBD);
@ -3251,7 +3265,8 @@ class Compiler
// TODO this method should have a better name
private TypeWrapper SigTypeToClassName(TypeWrapper type, TypeWrapper nullType)
{
if(type == VerifierTypeWrapper.UninitializedThis)
if(type == VerifierTypeWrapper.UninitializedThis
|| VerifierTypeWrapper.IsThis(type))
{
return clazz;
}

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

@ -434,6 +434,14 @@ class InstructionState
{
return VerifierTypeWrapper.Invalid;
}
if(VerifierTypeWrapper.IsThis(type1))
{
type1 = ((VerifierTypeWrapper)type1).UnderlyingType;
}
if(VerifierTypeWrapper.IsThis(type2))
{
type2 = ((VerifierTypeWrapper)type2).UnderlyingType;
}
if(type1.IsUnloadable || type2.IsUnloadable)
{
return VerifierTypeWrapper.Unloadable;
@ -820,6 +828,10 @@ class InstructionState
{
stackEnd++;
}
if(VerifierTypeWrapper.IsThis(type))
{
type = ((VerifierTypeWrapper)type).UnderlyingType;
}
return type;
}
@ -993,7 +1005,12 @@ struct StackState
{
throw new VerifyError("Unable to pop operand off an empty stack");
}
return state.GetStackByIndex(sp - 1);
TypeWrapper type = state.GetStackByIndex(sp - 1);
if(VerifierTypeWrapper.IsThis(type))
{
type = ((VerifierTypeWrapper)type).UnderlyingType;
}
return type;
}
internal TypeWrapper PopAnyType()
@ -1002,7 +1019,12 @@ struct StackState
{
throw new VerifyError("Unable to pop operand off an empty stack");
}
return state.GetStackByIndex(--sp);
TypeWrapper type = state.GetStackByIndex(--sp);
if(VerifierTypeWrapper.IsThis(type))
{
type = ((VerifierTypeWrapper)type).UnderlyingType;
}
return type;
}
internal TypeWrapper PopType(TypeWrapper baseType)
@ -1114,7 +1136,7 @@ class VerifierTypeWrapper : TypeWrapper
{
internal static readonly TypeWrapper Invalid = null;
internal static readonly TypeWrapper Null = new VerifierTypeWrapper("null", 0, null);
internal static readonly TypeWrapper UninitializedThis = new VerifierTypeWrapper("this", 0, null);
internal static readonly TypeWrapper UninitializedThis = new VerifierTypeWrapper("uninitialized-this", 0, null);
internal static readonly TypeWrapper Unloadable = new UnloadableTypeWrapper("<verifier>");
private int index;
@ -1143,6 +1165,16 @@ class VerifierTypeWrapper : TypeWrapper
return new VerifierTypeWrapper("ret", bytecodeIndex, null);
}
// NOTE the "this" type is special, it can only exist in local[0] and on the stack
// as soon as the type on the stack is merged or popped it turns into its underlying type.
// It exists to capture the verification rules for non-virtual base class method invocation in .NET 2.0,
// which requires that the invocation is done on a "this" reference that was directly loaded onto the
// stack (using ldarg_0).
internal static TypeWrapper MakeThis(TypeWrapper type)
{
return new VerifierTypeWrapper("this", 0, type);
}
internal static bool IsNew(TypeWrapper w)
{
return w != null && w.IsVerifierType && w.Name == "new";
@ -1158,6 +1190,11 @@ class VerifierTypeWrapper : TypeWrapper
return w == Null || w.IsUnloadable;
}
internal static bool IsThis(TypeWrapper w)
{
return w != null && w.IsVerifierType && w.Name == "this";
}
internal int Index
{
get
@ -1353,9 +1390,11 @@ class MethodAnalyzer
// start by computing the initial state, the stack is empty and the locals contain the arguments
state[0] = new InstructionState(method.MaxLocals, method.MaxStack);
TypeWrapper thisType;
int firstNonArgLocalIndex = 0;
if(!method.IsStatic)
{
thisType = VerifierTypeWrapper.MakeThis(wrapper);
// this reference. If we're a constructor, the this reference is uninitialized.
if(method.Name == "<init>")
{
@ -1364,9 +1403,13 @@ class MethodAnalyzer
}
else
{
state[0].SetLocalType(firstNonArgLocalIndex++, wrapper, -1);
state[0].SetLocalType(firstNonArgLocalIndex++, thisType, -1);
}
}
else
{
thisType = null;
}
// mw can be null when we're invoked from IsSideEffectFreeStaticInitializer
TypeWrapper[] argTypeWrappers = mw == null ? TypeWrapper.EmptyArray : mw.GetParameters();
for(int i = 0; i < argTypeWrappers.Length; i++)
@ -1766,6 +1809,10 @@ class MethodAnalyzer
// are now initialized
if(type == VerifierTypeWrapper.UninitializedThis)
{
if(s.GetLocalTypeEx(0) == type)
{
s.SetLocalType(0, thisType, i);
}
s.MarkInitialized(type, wrapper, i);
s.SetUnitializedThis(false);
}
@ -2667,7 +2714,7 @@ class MethodAnalyzer
{
LocalVar v = new LocalVar();
v.local = instructions[i].NormalizedArg1;
v.type = GetRawStackTypeWrapper(i, 0);
v.type = GetStackTypeWrapper(i, 0);
v.FindLvtEntry(method, i);
locals.Add(v);
localByStoreSite.Add(i + ":" + v.local, v);
@ -2879,6 +2926,7 @@ class MethodAnalyzer
instr.PatchOpCode(NormalizedByteCode.__dynamic_invokevirtual);
break;
case NormalizedByteCode.__invokespecial:
// TODO support dynamically instantiating an unloadable type
instr.SetHardError(HardError.LinkageError, AllocErrorMessage("Base class no longer loadable"));
break;
default:
@ -3174,7 +3222,7 @@ class MethodAnalyzer
else
{
Debug.Assert(IsStoreLocal(method.Instructions[store].NormalizedOpCode));
type = InstructionState.FindCommonBaseType(type, GetRawStackTypeWrapper(store, 0));
type = InstructionState.FindCommonBaseType(type, GetStackTypeWrapper(store, 0));
}
}
// we can't have an invalid type, because that would have failed verification earlier
@ -3206,7 +3254,14 @@ class MethodAnalyzer
{
local = new LocalVar();
local.local = localIndex;
local.type = type;
if(VerifierTypeWrapper.IsThis(type))
{
local.type = ((VerifierTypeWrapper)type).UnderlyingType;
}
else
{
local.type = type;
}
local.isArg = isArg;
if(JVM.Debug)
{
@ -3359,6 +3414,16 @@ class MethodAnalyzer
return state[index].GetStackHeight();
}
internal TypeWrapper GetStackTypeWrapper(int index, int pos)
{
TypeWrapper type = state[index].GetStackSlot(pos);
if(VerifierTypeWrapper.IsThis(type))
{
type = ((VerifierTypeWrapper)type).UnderlyingType;
}
return type;
}
internal TypeWrapper GetRawStackTypeWrapper(int index, int pos)
{
return state[index].GetStackSlot(pos);

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

@ -670,8 +670,11 @@ namespace IKVM.Internal
AttributeHelper.SetSourceFile(moduleBuilder, null);
}
AttributeHelper.SetJavaModule(moduleBuilder);
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, JVM.Debug });
assemblyBuilder.SetCustomAttribute(debugAttr);
if(JVM.Debug || !JVM.NoStackTraceInfo)
{
CustomAttributeBuilder debugAttr = new CustomAttributeBuilder(typeof(DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new object[] { true, JVM.Debug });
assemblyBuilder.SetCustomAttribute(debugAttr);
}
return moduleBuilder;
}