Ejemplo n.º 1
0
        bool IntroduceFixedStatements(List <ILNode> body, int i)
        {
            ILExpression initValue;
            ILVariable   pinnedVar;
            int          initEndPos;

            if (!MatchFixedInitializer(body, i, out pinnedVar, out initValue, out initEndPos))
            {
                return(false);
            }

            ILFixedStatement fixedStmt = body.ElementAtOrDefault(initEndPos) as ILFixedStatement;

            if (fixedStmt != null)
            {
                ILExpression expr = fixedStmt.BodyBlock.Body.LastOrDefault() as ILExpression;
                if (expr != null && expr.Code == ILCode.Stloc && expr.Operand == pinnedVar && IsNullOrZero(expr.Arguments[0]))
                {
                    // we found a second initializer for the existing fixed statement
                    fixedStmt.Initializers.Insert(0, initValue);
                    body.RemoveRange(i, initEndPos - i);
                    fixedStmt.BodyBlock.Body.RemoveAt(fixedStmt.BodyBlock.Body.Count - 1);
                    if (pinnedVar.Type.IsByReference)
                    {
                        pinnedVar.Type = new PointerType(((ByReferenceType)pinnedVar.Type).ElementType);
                    }
                    return(true);
                }
            }

            // find where pinnedVar is reset to 0:
            int j;

            for (j = initEndPos; j < body.Count; j++)
            {
                ILVariable   v2;
                ILExpression storedVal;
                // stloc(pinned_Var, conv.u(ldc.i4(0)))
                if (body[j].Match(ILCode.Stloc, out v2, out storedVal) && v2 == pinnedVar)
                {
                    if (IsNullOrZero(storedVal))
                    {
                        break;
                    }
                }
            }
            // Create fixed statement from i to j
            fixedStmt = new ILFixedStatement();
            fixedStmt.Initializers.Add(initValue);
            fixedStmt.BodyBlock = new ILBlock(body.GetRange(initEndPos, j - initEndPos)); // from initEndPos to j-1 (inclusive)
            body.RemoveRange(i + 1, Math.Min(j, body.Count - 1) - i);                     // from i+1 to j (inclusive)
            body[i] = fixedStmt;
            if (pinnedVar.Type.IsByReference)
            {
                pinnedVar.Type = new PointerType(((ByReferenceType)pinnedVar.Type).ElementType);
            }

            return(true);
        }
Ejemplo n.º 2
0
        bool MatchFixedInitializer(List <ILNode> body, int i, out ILVariable pinnedVar, out ILExpression initValue, out int nextPos)
        {
            if (body[i].Match(ILCode.Stloc, out pinnedVar, out initValue) && pinnedVar.IsPinned && !IsNullOrZero(initValue))
            {
                initValue = (ILExpression)body[i];
                nextPos   = i + 1;
                HandleStringFixing(pinnedVar, body, ref nextPos, ref initValue);
                return(true);
            }
            ILCondition  ifStmt = body[i] as ILCondition;
            ILExpression arrayLoadingExpr;

            if (ifStmt != null && MatchFixedArrayInitializerCondition(ifStmt.Condition, out arrayLoadingExpr))
            {
                ILVariable   arrayVariable = (ILVariable)arrayLoadingExpr.Operand;
                ILExpression trueValue;
                if (ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1 &&
                    ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out pinnedVar, out trueValue) &&
                    pinnedVar.IsPinned && IsNullOrZero(trueValue))
                {
                    if (ifStmt.FalseBlock != null && ifStmt.FalseBlock.Body.Count == 1 && ifStmt.FalseBlock.Body[0] is ILFixedStatement)
                    {
                        ILFixedStatement fixedStmt = (ILFixedStatement)ifStmt.FalseBlock.Body[0];
                        ILVariable       stlocVar;
                        ILExpression     falseValue;
                        if (fixedStmt.Initializers.Count == 1 && fixedStmt.BodyBlock.Body.Count == 0 &&
                            fixedStmt.Initializers[0].Match(ILCode.Stloc, out stlocVar, out falseValue) && stlocVar == pinnedVar)
                        {
                            ILVariable loadedVariable;
                            if (falseValue.Code == ILCode.Ldelema &&
                                falseValue.Arguments[0].Match(ILCode.Ldloc, out loadedVariable) && loadedVariable == arrayVariable &&
                                IsNullOrZero(falseValue.Arguments[1]))
                            {
                                // OK, we detected the pattern for fixing an array.
                                // Now check whether the loading expression was a store ot a temp. var
                                // that can be eliminated.
                                if (arrayLoadingExpr.Code == ILCode.Stloc)
                                {
                                    ILInlining inlining = new ILInlining(method);
                                    if (inlining.numLdloc.GetOrDefault(arrayVariable) == 2 &&
                                        inlining.numStloc.GetOrDefault(arrayVariable) == 1 && inlining.numLdloca.GetOrDefault(arrayVariable) == 0)
                                    {
                                        arrayLoadingExpr = arrayLoadingExpr.Arguments[0];
                                    }
                                }
                                initValue = new ILExpression(ILCode.Stloc, pinnedVar, arrayLoadingExpr);
                                nextPos   = i + 1;
                                return(true);
                            }
                        }
                    }
                }
            }
            initValue = null;
            nextPos   = -1;
            return(false);
        }
Ejemplo n.º 3
0
        bool MatchFixedInitializer(List <ILNode> body, int i, out ILVariable pinnedVar, out ILExpression initValue, out int nextPos)
        {
            if (body[i].Match(ILCode.Stloc, out pinnedVar, out initValue) && pinnedVar.IsPinned && !IsNullOrZero(initValue))
            {
                initValue = (ILExpression)body[i];
                nextPos   = i + 1;
                HandleStringFixing(pinnedVar, body, ref nextPos, ref initValue);
                return(true);
            }
            ILCondition  ifStmt = body[i] as ILCondition;
            ILExpression arrayLoadingExpr;

            if (ifStmt != null && MatchFixedArrayInitializerCondition(ifStmt.Condition, out arrayLoadingExpr))
            {
                ILVariable   arrayVariable = (ILVariable)arrayLoadingExpr.Operand;
                ILExpression trueValue;
                if (ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1 &&
                    ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out pinnedVar, out trueValue) &&
                    pinnedVar.IsPinned && IsNullOrZero(trueValue))
                {
                    if (ifStmt.FalseBlock != null && ifStmt.FalseBlock.Body.Count == 1 && ifStmt.FalseBlock.Body[0] is ILFixedStatement)
                    {
                        ILFixedStatement fixedStmt = (ILFixedStatement)ifStmt.FalseBlock.Body[0];
                        ILVariable       stlocVar;
                        ILExpression     falseValue;
                        if (fixedStmt.Initializers.Count == 1 && fixedStmt.BodyBlock.Body.Count == 0 &&
                            fixedStmt.Initializers[0].Match(ILCode.Stloc, out stlocVar, out falseValue) && stlocVar == pinnedVar)
                        {
                            ILVariable loadedVariable;
                            if (falseValue.Code == ILCode.Ldelema &&
                                falseValue.Arguments[0].Match(ILCode.Ldloc, out loadedVariable) && loadedVariable == arrayVariable &&
                                IsNullOrZero(falseValue.Arguments[1]))
                            {
                                initValue = new ILExpression(ILCode.Stloc, pinnedVar, arrayLoadingExpr);
                                nextPos   = i + 1;
                                return(true);
                            }
                        }
                    }
                }
            }
            initValue = null;
            nextPos   = -1;
            return(false);
        }