Example #1
0
        bool TransformArrayInitializers(ILBlockBase block, List <ILNode> body, ILExpression expr, int pos)
        {
            ILVariable    v, v3;
            ILExpression  newarrExpr;
            ITypeDefOrRef elementType;
            ILExpression  lengthExpr;
            int           arrayLength;

            if (expr.Match(ILCode.Stloc, out v, out newarrExpr) &&
                newarrExpr.Match(ILCode.Newarr, out elementType, out lengthExpr) &&
                lengthExpr.Match(ILCode.Ldc_I4, out arrayLength) &&
                arrayLength > 0)
            {
                ILExpression[] newArr;
                int            initArrayPos;
                if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, new SZArraySig(elementType.ToTypeSig()), arrayLength, out newArr, out initArrayPos))
                {
                    var arrayType = new ArraySig(elementType.ToTypeSig(), 1, new uint[1], new int[1]);
                    arrayType.Sizes[0] = (uint)(arrayLength + 1);
                    var newStloc = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, arrayType.ToTypeDefOrRef(), newArr));
                    body[pos].AddSelfAndChildrenRecursiveILRanges(newStloc.ILRanges);
                    body[initArrayPos].AddSelfAndChildrenRecursiveILRanges(newStloc.ILRanges);
                    body[pos] = newStloc;
                    body.RemoveAt(initArrayPos);
                }
                // Put in a limit so that we don't consume too much memory if the code allocates a huge array
                // and populates it extremely sparsly. However, 255 "null" elements in a row actually occur in the Mono C# compiler!
                const int           maxConsecutiveDefaultValueExpressions = 300;
                List <ILExpression> operands     = new List <ILExpression>();
                int numberOfInstructionsToRemove = 0;
                for (int j = pos + 1; j < body.Count; j++)
                {
                    ILExpression nextExpr = body[j] as ILExpression;
                    int          arrayPos;
                    if (nextExpr != null &&
                        nextExpr.Code.IsStoreToArray() &&
                        nextExpr.Arguments[0].Match(ILCode.Ldloc, out v3) &&
                        v == v3 &&
                        nextExpr.Arguments[1].Match(ILCode.Ldc_I4, out arrayPos) &&
                        arrayPos >= operands.Count &&
                        arrayPos <= operands.Count + maxConsecutiveDefaultValueExpressions &&
                        !nextExpr.Arguments[2].ContainsReferenceTo(v3))
                    {
                        while (operands.Count < arrayPos)
                        {
                            operands.Add(new ILExpression(ILCode.DefaultValue, elementType));
                        }
                        operands.Add(nextExpr.Arguments[2]);
                        numberOfInstructionsToRemove++;
                    }
                    else
                    {
                        break;
                    }
                }
                if (operands.Count == arrayLength)
                {
                    var arrayType = new ArraySig(elementType.ToTypeSig(), 1, new uint[1], new int[1]);
                    arrayType.Sizes[0] = (uint)(arrayLength + 1);
                    expr.Arguments[0]  = new ILExpression(ILCode.InitArray, arrayType.ToTypeDefOrRef(), operands);
                    newarrExpr.AddSelfAndChildrenRecursiveILRanges(expr.ILRanges);
                    for (int i = 0; i < numberOfInstructionsToRemove; i++)
                    {
                        body[pos + 1 + i].AddSelfAndChildrenRecursiveILRanges(expr.ILRanges);
                    }
                    body.RemoveRange(pos + 1, numberOfInstructionsToRemove);

                    GetILInlining(method).InlineIfPossible(block, body, ref pos);
                    return(true);
                }
            }
            return(false);
        }
Example #2
0
        bool TransformMultidimensionalArrayInitializers(ILBlockBase block, List <ILNode> body, ILExpression expr, int pos)
        {
            ILVariable          v;
            ILExpression        newarrExpr;
            IMethod             ctor;
            List <ILExpression> ctorArgs;
            TypeSpec            arySpec;
            ArraySigBase        arrayType;

            if (expr.Match(ILCode.Stloc, out v, out newarrExpr) &&
                newarrExpr.Match(ILCode.Newobj, out ctor, out ctorArgs) &&
                (arySpec = (ctor.DeclaringType as TypeSpec)) != null &&
                (arrayType = arySpec.TypeSig.RemovePinnedAndModifiers() as ArraySigBase) != null &&
                arrayType.Rank == ctorArgs.Count)
            {
                // Clone the type, so we can muck about with the Dimensions
                var multAry      = new ArraySig(arrayType.Next, arrayType.Rank, new uint[arrayType.Rank], new int[arrayType.Rank]);
                var arrayLengths = new int[multAry.Rank];
                for (int i = 0; i < multAry.Rank; i++)
                {
                    if (!ctorArgs[i].Match(ILCode.Ldc_I4, out arrayLengths[i]))
                    {
                        return(false);
                    }
                    if (arrayLengths[i] <= 0)
                    {
                        return(false);
                    }
                    multAry.Sizes[i]       = (uint)(arrayLengths[i] + 1);
                    multAry.LowerBounds[i] = 0;
                }

                var            totalElements = arrayLengths.Aggregate(1, (t, l) => t * l);
                ILExpression[] newArr;
                int            initArrayPos;
                if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, multAry, totalElements, out newArr, out initArrayPos))
                {
                    var newStloc = new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.InitArray, multAry.ToTypeDefOrRef(), newArr));
                    body[pos].AddSelfAndChildrenRecursiveILRanges(newStloc.ILRanges);
                    body[initArrayPos].AddSelfAndChildrenRecursiveILRanges(newStloc.ILRanges);
                    body[pos] = newStloc;
                    body.RemoveAt(initArrayPos);
                    return(true);
                }
            }
            return(false);
        }