コード例 #1
0
ファイル: LocalVars.cs プロジェクト: gongfuPanada/ikvm-fork
 private static void FindLvtEntry(LocalVar lv, ClassFile.Method method, int instructionIndex)
 {
     ClassFile.Method.LocalVariableTableEntry[] lvt = method.LocalVariableTableAttribute;
     if (lvt != null)
     {
         int  pc      = method.Instructions[instructionIndex].PC;
         int  nextPC  = method.Instructions[instructionIndex + 1].PC;
         bool isStore = IsStoreLocal(method.Instructions[instructionIndex].NormalizedOpCode);
         foreach (ClassFile.Method.LocalVariableTableEntry e in lvt)
         {
             // TODO validate the contents of the LVT entry
             if (e.index == lv.local &&
                 (e.start_pc <= pc || (e.start_pc == nextPC && isStore)) &&
                 e.start_pc + e.length > pc)
             {
                 lv.name     = e.name;
                 lv.start_pc = e.start_pc;
                 lv.end_pc   = e.start_pc + e.length;
                 break;
             }
         }
     }
 }
コード例 #2
0
ファイル: LocalVars.cs プロジェクト: gongfuPanada/ikvm-fork
    internal LocalVarInfo(CodeInfo ma, ClassFile classFile, ClassFile.Method method, UntangledExceptionTable exceptions, MethodWrapper mw, ClassLoaderWrapper classLoader)
    {
        Dictionary <int, string>[] localStoreReaders = FindLocalVariables(ma, mw, classFile, method);

        // now that we've done the code flow analysis, we can do a liveness analysis on the local variables
        ClassFile.Method.Instruction[] instructions     = method.Instructions;
        Dictionary <long, LocalVar>    localByStoreSite = new Dictionary <long, LocalVar>();
        List <LocalVar> locals = new List <LocalVar>();

        for (int i = 0; i < localStoreReaders.Length; i++)
        {
            if (localStoreReaders[i] != null)
            {
                VisitLocalLoads(ma, method, locals, localByStoreSite, localStoreReaders[i], i, classLoader.EmitDebugInfo);
            }
        }
        Dictionary <LocalVar, LocalVar> forwarders = new Dictionary <LocalVar, LocalVar>();

        if (classLoader.EmitDebugInfo)
        {
            InstructionFlags[] flags = MethodAnalyzer.ComputePartialReachability(ma, method.Instructions, exceptions, 0, false);
            // if we're emitting debug info, we need to keep dead stores as well...
            for (int i = 0; i < instructions.Length; i++)
            {
                if ((flags[i] & InstructionFlags.Reachable) != 0 &&
                    IsStoreLocal(instructions[i].NormalizedOpCode))
                {
                    if (!localByStoreSite.ContainsKey(MakeKey(i, instructions[i].NormalizedArg1)))
                    {
                        LocalVar v = new LocalVar();
                        v.local = instructions[i].NormalizedArg1;
                        v.type  = ma.GetStackTypeWrapper(i, 0);
                        FindLvtEntry(v, method, i);
                        locals.Add(v);
                        localByStoreSite.Add(MakeKey(i, v.local), v);
                    }
                }
            }
            // to make the debugging experience better, we have to trust the
            // LocalVariableTable (unless it's clearly bogus) and merge locals
            // together that are the same according to the LVT
            for (int i = 0; i < locals.Count - 1; i++)
            {
                for (int j = i + 1; j < locals.Count; j++)
                {
                    LocalVar v1 = (LocalVar)locals[i];
                    LocalVar v2 = (LocalVar)locals[j];
                    if (v1.name != null && v1.name == v2.name && v1.start_pc == v2.start_pc && v1.end_pc == v2.end_pc)
                    {
                        // we can only merge if the resulting type is valid (this protects against incorrect
                        // LVT data, but is also needed for constructors, where the uninitialized this is a different
                        // type from the initialized this)
                        TypeWrapper tw = InstructionState.FindCommonBaseType(v1.type, v2.type);
                        if (tw != VerifierTypeWrapper.Invalid)
                        {
                            v1.isArg |= v2.isArg;
                            v1.type   = tw;
                            forwarders.Add(v2, v1);
                            locals.RemoveAt(j);
                            j--;
                        }
                    }
                }
            }
        }
        else
        {
            for (int i = 0; i < locals.Count - 1; i++)
            {
                for (int j = i + 1; j < locals.Count; j++)
                {
                    LocalVar v1 = (LocalVar)locals[i];
                    LocalVar v2 = (LocalVar)locals[j];
                    // if the two locals are the same, we merge them, this is a small
                    // optimization, it should *not* be required for correctness.
                    if (v1.local == v2.local && v1.type == v2.type)
                    {
                        v1.isArg |= v2.isArg;
                        forwarders.Add(v2, v1);
                        locals.RemoveAt(j);
                        j--;
                    }
                }
            }
        }
        invokespecialLocalVars = new LocalVar[instructions.Length][];
        localVars = new LocalVar[instructions.Length];
        for (int i = 0; i < localVars.Length; i++)
        {
            LocalVar v = null;
            if (localStoreReaders[i] != null)
            {
                Debug.Assert(IsLoadLocal(instructions[i].NormalizedOpCode));
                // lame way to look up the local variable for a load
                // (by indirecting through a corresponding store)
                foreach (int store in localStoreReaders[i].Keys)
                {
                    v = localByStoreSite[MakeKey(store, instructions[i].NormalizedArg1)];
                    break;
                }
            }
            else
            {
                if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial)
                {
                    invokespecialLocalVars[i] = new LocalVar[method.MaxLocals];
                    for (int j = 0; j < invokespecialLocalVars[i].Length; j++)
                    {
                        localByStoreSite.TryGetValue(MakeKey(i, j), out invokespecialLocalVars[i][j]);
                    }
                }
                else
                {
                    localByStoreSite.TryGetValue(MakeKey(i, instructions[i].NormalizedArg1), out v);
                }
            }
            if (v != null)
            {
                LocalVar fwd;
                if (forwarders.TryGetValue(v, out fwd))
                {
                    v = fwd;
                }
                localVars[i] = v;
            }
        }
        this.allLocalVars = locals.ToArray();
    }
コード例 #3
0
ファイル: LocalVars.cs プロジェクト: gongfuPanada/ikvm-fork
    private static void VisitLocalLoads(CodeInfo codeInfo, ClassFile.Method method, List <LocalVar> locals, Dictionary <long, LocalVar> localByStoreSite, Dictionary <int, string> storeSites, int instructionIndex, bool debug)
    {
        Debug.Assert(IsLoadLocal(method.Instructions[instructionIndex].NormalizedOpCode));
        LocalVar    local      = null;
        TypeWrapper type       = VerifierTypeWrapper.Null;
        int         localIndex = method.Instructions[instructionIndex].NormalizedArg1;
        bool        isArg      = false;

        foreach (int store in storeSites.Keys)
        {
            if (store == -1)
            {
                // it's a method argument, it has no initial store, but the type is simply the parameter type
                type  = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(0, localIndex));
                isArg = true;
            }
            else
            {
                if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__invokespecial)
                {
                    type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(store + 1, localIndex));
                }
                else if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__static_error)
                {
                    // it's an __invokespecial that turned into a __static_error
                    // (since a __static_error doesn't continue, we don't need to set type)
                }
                else
                {
                    Debug.Assert(IsStoreLocal(method.Instructions[store].NormalizedOpCode));
                    type = InstructionState.FindCommonBaseType(type, codeInfo.GetStackTypeWrapper(store, 0));
                }
            }
            // we can't have an invalid type, because that would have failed verification earlier
            Debug.Assert(type != VerifierTypeWrapper.Invalid);

            LocalVar l;
            if (localByStoreSite.TryGetValue(MakeKey(store, localIndex), out l))
            {
                if (local == null)
                {
                    local = l;
                }
                else if (local != l)
                {
                    // If we've already defined a LocalVar and we find another one, then we merge them
                    // together.
                    // This happens for the following code fragment:
                    //
                    // int i = -1;
                    // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {}
                    // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {}
                    // System.out.println(i);
                    //
                    local = MergeLocals(locals, localByStoreSite, local, l);
                }
            }
        }
        if (local == null)
        {
            local       = new LocalVar();
            local.local = localIndex;
            if (VerifierTypeWrapper.IsThis(type))
            {
                local.type = ((VerifierTypeWrapper)type).UnderlyingType;
            }
            else
            {
                local.type = type;
            }
            local.isArg = isArg;
            if (debug)
            {
                FindLvtEntry(local, method, instructionIndex);
            }
            locals.Add(local);
        }
        else
        {
            local.isArg |= isArg;
            local.type   = InstructionState.FindCommonBaseType(local.type, type);
            Debug.Assert(local.type != VerifierTypeWrapper.Invalid);
        }
        foreach (int store in storeSites.Keys)
        {
            LocalVar v;
            if (!localByStoreSite.TryGetValue(MakeKey(store, localIndex), out v))
            {
                localByStoreSite[MakeKey(store, localIndex)] = local;
            }
            else if (v != local)
            {
                local = MergeLocals(locals, localByStoreSite, local, v);
            }
        }
    }
コード例 #4
0
ファイル: LocalVars.cs プロジェクト: gongfuPanada/ikvm-fork
    private static Dictionary <int, string>[] FindLocalVariablesImpl(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, FindLocalVarState[] state)
    {
        ClassFile.Method.Instruction[] instructions = method.Instructions;
        ExceptionTableEntry[]          exceptions   = method.ExceptionTable;
        int maxLocals = method.MaxLocals;

        Dictionary <int, string>[] localStoreReaders = new Dictionary <int, string> [instructions.Length];
        bool done = false;

        while (!done)
        {
            done = true;
            for (int i = 0; i < instructions.Length; i++)
            {
                if (state[i].changed)
                {
                    done             = false;
                    state[i].changed = false;

                    FindLocalVarState curr = state[i].Copy();

                    for (int j = 0; j < exceptions.Length; j++)
                    {
                        if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex)
                        {
                            state[exceptions[j].handlerIndex].Merge(curr);
                        }
                    }

                    if (IsLoadLocal(instructions[i].NormalizedOpCode) &&
                        (instructions[i].NormalizedOpCode != NormalizedByteCode.__aload || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i + 1, 0))))
                    {
                        if (localStoreReaders[i] == null)
                        {
                            localStoreReaders[i] = new Dictionary <int, string>();
                        }
                        for (int j = 0; j < curr.sites[instructions[i].NormalizedArg1].Count; j++)
                        {
                            localStoreReaders[i][curr.sites[instructions[i].NormalizedArg1][j]] = "";
                        }
                    }

                    if (IsStoreLocal(instructions[i].NormalizedOpCode) &&
                        (instructions[i].NormalizedOpCode != NormalizedByteCode.__astore || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i, 0))))
                    {
                        curr.Store(i, instructions[i].NormalizedArg1);
                        // if this is a store at the end of an exception block,
                        // we need to propagate the new state to the exception handler
                        for (int j = 0; j < exceptions.Length; j++)
                        {
                            if (exceptions[j].endIndex == i + 1)
                            {
                                state[exceptions[j].handlerIndex].Merge(curr);
                            }
                        }
                    }

                    if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial)
                    {
                        ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instructions[i].Arg1);
                        if (ReferenceEquals(cpi.Name, StringConstants.INIT))
                        {
                            TypeWrapper type = codeInfo.GetRawStackTypeWrapper(i, cpi.GetArgTypes().Length);
                            // after we've invoked the constructor, the uninitialized references
                            // are now initialized
                            if (type == VerifierTypeWrapper.UninitializedThis ||
                                VerifierTypeWrapper.IsNew(type))
                            {
                                for (int j = 0; j < maxLocals; j++)
                                {
                                    if (codeInfo.GetLocalTypeWrapper(i, j) == type)
                                    {
                                        curr.Store(i, j);
                                    }
                                }
                            }
                        }
                    }
                    else if (instructions[i].NormalizedOpCode == NormalizedByteCode.__goto_finally)
                    {
                        int handler = instructions[i].HandlerIndex;

                        // Normally a store at the end of a try block doesn't affect the handler block,
                        // but in the case of a finally handler it does, so we need to make sure that
                        // we merge here in case the try block ended with a store.
                        state[handler].Merge(curr);

                        // Now we recursively analyse the handler and afterwards merge the endfault locations back to us
                        FindLocalVarState[] handlerState = new FindLocalVarState[instructions.Length];
                        handlerState[handler].Merge(curr);
                        curr = new FindLocalVarState();
                        FindLocalVariablesImpl(codeInfo, classFile, method, handlerState);

                        // Merge back to the target of our __goto_finally
                        for (int j = 0; j < handlerState.Length; j++)
                        {
                            if (instructions[j].NormalizedOpCode == NormalizedByteCode.__athrow &&
                                codeInfo.HasState(j) &&
                                VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0)) &&
                                ((VerifierTypeWrapper)codeInfo.GetRawStackTypeWrapper(j, 0)).Index == handler)
                            {
                                curr.Merge(handlerState[j]);
                            }
                        }
                    }

                    switch (ByteCodeMetaData.GetFlowControl(instructions[i].NormalizedOpCode))
                    {
                    case ByteCodeFlowControl.Switch:
                    {
                        for (int j = 0; j < instructions[i].SwitchEntryCount; j++)
                        {
                            state[instructions[i].GetSwitchTargetIndex(j)].Merge(curr);
                        }
                        state[instructions[i].DefaultTarget].Merge(curr);
                        break;
                    }

                    case ByteCodeFlowControl.Branch:
                        state[instructions[i].TargetIndex].Merge(curr);
                        break;

                    case ByteCodeFlowControl.CondBranch:
                        state[instructions[i].TargetIndex].Merge(curr);
                        state[i + 1].Merge(curr);
                        break;

                    case ByteCodeFlowControl.Return:
                    case ByteCodeFlowControl.Throw:
                        break;

                    case ByteCodeFlowControl.Next:
                        state[i + 1].Merge(curr);
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
            }
        }
        return(localStoreReaders);
    }
コード例 #5
0
ファイル: LocalVars.cs プロジェクト: gongfuPanada/ikvm-fork
    private static Dictionary <int, string>[] FindLocalVariables(CodeInfo codeInfo, MethodWrapper mw, ClassFile classFile, ClassFile.Method method)
    {
        FindLocalVarState[] state = new FindLocalVarState[method.Instructions.Length];
        state[0].changed = true;
        state[0].sites   = new FindLocalVarStoreSite[method.MaxLocals];
        TypeWrapper[] parameters = mw.GetParameters();
        int           argpos     = 0;

        if (!mw.IsStatic)
        {
            state[0].sites[argpos++].Add(-1);
        }
        for (int i = 0; i < parameters.Length; i++)
        {
            state[0].sites[argpos++].Add(-1);
            if (parameters[i].IsWidePrimitive)
            {
                argpos++;
            }
        }
        return(FindLocalVariablesImpl(codeInfo, classFile, method, state));
    }