From 7cc7744ec9fdbed85c2350554623bdbe0e297c7c Mon Sep 17 00:00:00 2001 From: jfrijters Date: Thu, 29 Dec 2005 09:57:41 +0000 Subject: [PATCH] *** empty log message *** --- runtime/compiler.cs | 59 ++++++++++++++++++++------------- runtime/verifier.cs | 79 +++++++++++++++++++++++++++++++++++++++++---- runtime/vm.cs | 7 ++-- 3 files changed, 114 insertions(+), 31 deletions(-) diff --git a/runtime/compiler.cs b/runtime/compiler.cs index d15ce850..13829366 100644 --- a/runtime/compiler.cs +++ b/runtime/compiler.cs @@ -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 // 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; } diff --git a/runtime/verifier.cs b/runtime/verifier.cs index 41c81e6a..62c72140 100644 --- a/runtime/verifier.cs +++ b/runtime/verifier.cs @@ -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(""); 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 == "") { @@ -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); diff --git a/runtime/vm.cs b/runtime/vm.cs index d95bdbba..b622fcb2 100644 --- a/runtime/vm.cs +++ b/runtime/vm.cs @@ -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; }