コード例 #1
0
        public void UncheckedAdd(int capacity)
        {
            Debug.Assert(capacity >= 0);

            var builder = new ArrayBuilder <T>(capacity);

            for (int i = 0; i < capacity; i++)
            {
                builder.UncheckedAdd(default(T));
            }

            VerifyBuilderContents(Enumerable.Repeat(default(T), capacity), builder);
        }
コード例 #2
0
ファイル: CompilerScope.cs プロジェクト: csharpHub/Theraot
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection <ParameterExpression> vars)
        {
            if (NearestHoistedLocals != null && vars.Count > 0)
            {
                // Find what array each variable is on & its index
                var indexes = new ArrayBuilder <long>(vars.Count);

                foreach (var variable in vars)
                {
                    // For each variable, find what array it's defined on
                    ulong parents = 0;
                    var   locals  = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable))
                    {
                        parents++;
                        if (locals.Parent == null)
                        {
                            Debug.Fail(string.Empty);
                        }
                        else
                        {
                            locals = locals.Parent;
                        }
                    }

                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    var index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.UncheckedAdd((long)index);
                }

                EmitGet(NearestHoistedLocals.SelfVariable);
                lc.EmitConstantArray(indexes.ToArray());
                lc.IL.Emit(OpCodes.Call, CachedReflectionInfo.RuntimeOpsCreateRuntimeVariablesObjectArrayInt64Array);
            }
            else
            {
                // No visible variables
                lc.IL.Emit(OpCodes.Call, CachedReflectionInfo.RuntimeOpsCreateRuntimeVariables);
            }
        }
コード例 #3
0
        private bool TryEmitHashtableSwitch(SwitchExpression node, CompilationFlags flags)
        {
            // If we have a comparison other than string equality, bail
            MethodInfo equality = String_op_Equality_String_String;

            if (equality != null && !equality.IsStatic)
            {
                equality = null;
            }

            if (node.Comparison != equality)
            {
                return(false);
            }

            // All test values must be constant.
            int tests = 0;

            foreach (SwitchCase c in node.Cases)
            {
                foreach (Expression t in c.TestValues)
                {
                    if (!(t is ConstantExpression))
                    {
                        return(false);
                    }
                    tests++;
                }
            }

            // Must have >= 7 labels for it to be worth it.
            if (tests < 7)
            {
                return(false);
            }

            // If we're in a DynamicMethod, we could just build the dictionary
            // immediately. But that would cause the two code paths to be more
            // different than they really need to be.
            var initializers = new List <ElementInit>(tests);
            var cases        = new ArrayBuilder <SwitchCase>(node.Cases.Count);

            int        nullCase = -1;
            MethodInfo add      = DictionaryOfStringInt32_Add_String_Int32;

            for (int i = 0, n = node.Cases.Count; i < n; i++)
            {
                foreach (ConstantExpression t in node.Cases[i].TestValues)
                {
                    if (t.Value != null)
                    {
                        initializers.Add(Expression.ElementInit(add, t, Expression.Constant(i)));
                    }
                    else
                    {
                        nullCase = i;
                    }
                }
                cases.UncheckedAdd(Expression.SwitchCase(node.Cases[i].Body, Expression.Constant(i)));
            }

            // Create the field to hold the lazily initialized dictionary
            MemberExpression dictField = CreateLazyInitializedField <Dictionary <string, int> >("dictionarySwitch");

            // If we happen to initialize it twice (multithreaded case), it's
            // not the end of the world. The C# compiler does better here by
            // emitting a volatile access to the field.
            Expression dictInit = Expression.Condition(
                Expression.Equal(dictField, Expression.Constant(null, dictField.Type)),
                Expression.Assign(
                    dictField,
                    Expression.ListInit(
                        Expression.New(
                            DictionaryOfStringInt32_Ctor_Int32,
                            Expression.Constant(initializers.Count)
                            ),
                        initializers
                        )
                    ),
                dictField
                );

            //
            // Create a tree like:
            //
            // switchValue = switchValueExpression;
            // if (switchValue == null) {
            //     switchIndex = nullCase;
            // } else {
            //     if (_dictField == null) {
            //         _dictField = new Dictionary<string, int>(count) { { ... }, ... };
            //     }
            //     if (!_dictField.TryGetValue(switchValue, out switchIndex)) {
            //         switchIndex = -1;
            //     }
            // }
            // switch (switchIndex) {
            //     case 0: ...
            //     case 1: ...
            //     ...
            //     default:
            // }
            //
            var switchValue = Expression.Variable(typeof(string), "switchValue");
            var switchIndex = Expression.Variable(typeof(int), "switchIndex");
            var reduced     = Expression.Block(
                new[] { switchIndex, switchValue },
                Expression.Assign(switchValue, node.SwitchValue),
                Expression.IfThenElse(
                    Expression.Equal(switchValue, Expression.Constant(null, typeof(string))),
                    Expression.Assign(switchIndex, Expression.Constant(nullCase)),
                    Expression.IfThenElse(
                        Expression.Call(dictInit, "TryGetValue", null, switchValue, switchIndex),
                        Utils.Empty(),
                        Expression.Assign(switchIndex, Expression.Constant(-1))
                        )
                    ),
                Expression.Switch(node.Type, switchIndex, node.DefaultBody, null, cases.ToReadOnly())
                );

            EmitExpression(reduced, flags);
            return(true);
        }
コード例 #4
0
ファイル: BinaryExpression.cs プロジェクト: AtsushiKan/corefx
        private Expression ReduceIndex()
        {
            // left[a0, a1, ... aN] (op)= r
            //
            // ... is reduced into ...
            //
            // tempObj = left
            // tempArg0 = a0
            // ...
            // tempArgN = aN
            // tempValue = tempObj[tempArg0, ... tempArgN] (op) r
            // tempObj[tempArg0, ... tempArgN] = tempValue

            var index = (IndexExpression)Left;

            var vars = new ArrayBuilder<ParameterExpression>(index.ArgumentCount + 2);
            var exprs = new ArrayBuilder<Expression>(index.ArgumentCount + 3);

            ParameterExpression tempObj = Expression.Variable(index.Object.Type, "tempObj");
            vars.UncheckedAdd(tempObj);
            exprs.UncheckedAdd(Expression.Assign(tempObj, index.Object));

            int n = index.ArgumentCount;
            var tempArgs = new ArrayBuilder<Expression>(n);
            for (var i = 0; i < n; i++)
            {
                Expression arg = index.GetArgument(i);
                ParameterExpression tempArg = Expression.Variable(arg.Type, "tempArg" + i);
                vars.UncheckedAdd(tempArg);
                tempArgs.UncheckedAdd(tempArg);
                exprs.UncheckedAdd(Expression.Assign(tempArg, arg));
            }

            IndexExpression tempIndex = Expression.MakeIndex(tempObj, index.Indexer, tempArgs.ToReadOnly());

            // tempValue = tempObj[tempArg0, ... tempArgN] (op) r
            ExpressionType binaryOp = GetBinaryOpFromAssignmentOp(NodeType);
            Expression op = Expression.MakeBinary(binaryOp, tempIndex, Right, false, Method);
            LambdaExpression conversion = GetConversion();
            if (conversion != null)
            {
                op = Expression.Invoke(conversion, op);
            }
            ParameterExpression tempValue = Expression.Variable(op.Type, "tempValue");
            vars.UncheckedAdd(tempValue);
            exprs.UncheckedAdd(Expression.Assign(tempValue, op));

            // tempObj[tempArg0, ... tempArgN] = tempValue
            exprs.UncheckedAdd(Expression.Assign(tempIndex, tempValue));

            return Expression.Block(vars.ToReadOnly(), exprs.ToReadOnly());
        }
コード例 #5
0
        private Result RewriteMemberInitExpression(Expression expr, Stack stack)
        {
            var node = (MemberInitExpression)expr;

            // Constructor runs on initial stack.
            Result        result       = RewriteExpression(node.NewExpression, stack);
            Expression    rewrittenNew = result.Node;
            RewriteAction action       = result.Action;

            ReadOnlyCollection <MemberBinding> bindings = node.Bindings;
            int count = bindings.Count;

            BindingRewriter[] bindingRewriters = new BindingRewriter[count];

            for (int i = 0; i < count; i++)
            {
                MemberBinding binding = bindings[i];

                // Bindings run on non-empty stack (the object instance is on it).
                BindingRewriter rewriter = BindingRewriter.Create(binding, this, Stack.NonEmpty);
                bindingRewriters[i] = rewriter;

                action |= rewriter.Action;
            }

            switch (action)
            {
            case RewriteAction.None:
                break;

            case RewriteAction.Copy:
                MemberBinding[] newBindings = new MemberBinding[count];
                for (int i = 0; i < count; i++)
                {
                    newBindings[i] = bindingRewriters[i].AsBinding();
                }
                expr = new MemberInitExpression((NewExpression)rewrittenNew, new TrueReadOnlyCollection <MemberBinding>(newBindings));
                break;

            case RewriteAction.SpillStack:
                bool isRefNew = IsRefInstance(node.NewExpression);

                var comma = new ArrayBuilder <Expression>(count + 2 + (isRefNew ? 1 : 0));

                ParameterExpression tempNew = MakeTemp(rewrittenNew.Type);
                comma.UncheckedAdd(new AssignBinaryExpression(tempNew, rewrittenNew));

                ParameterExpression refTempNew = tempNew;
                if (isRefNew)
                {
                    refTempNew = MakeTemp(tempNew.Type.MakeByRefType());
                    comma.UncheckedAdd(new ByRefAssignBinaryExpression(refTempNew, tempNew));
                }

                for (int i = 0; i < count; i++)
                {
                    BindingRewriter cr       = bindingRewriters[i];
                    Expression      initExpr = cr.AsExpression(refTempNew);
                    comma.UncheckedAdd(initExpr);
                }

                comma.UncheckedAdd(tempNew);

                expr = MakeBlock(comma);
                break;

            default:
                throw ContractUtils.Unreachable;
            }
            return(new Result(action, expr));
        }
コード例 #6
0
        private Result RewriteListInitExpression(Expression expr, Stack stack)
        {
            var node = (ListInitExpression)expr;

            // Constructor runs on initial stack.
            Result        newResult    = RewriteExpression(node.NewExpression, stack);
            Expression    rewrittenNew = newResult.Node;
            RewriteAction action       = newResult.Action;

            ReadOnlyCollection <ElementInit> inits = node.Initializers;
            int count = inits.Count;

            ChildRewriter[] cloneCrs = new ChildRewriter[count];

            for (int i = 0; i < count; i++)
            {
                ElementInit init = inits[i];

                // Initializers all run on non-empty stack (the list instance is on it).
                var cr = new ChildRewriter(this, Stack.NonEmpty, init.Arguments.Count);
                cr.Add(init.Arguments);

                action     |= cr.Action;
                cloneCrs[i] = cr;
            }

            switch (action)
            {
            case RewriteAction.None:
                break;

            case RewriteAction.Copy:
                ElementInit[] newInits = new ElementInit[count];
                for (int i = 0; i < count; i++)
                {
                    ChildRewriter cr = cloneCrs[i];
                    if (cr.Action == RewriteAction.None)
                    {
                        newInits[i] = inits[i];
                    }
                    else
                    {
                        newInits[i] = new ElementInit(inits[i].AddMethod, new TrueReadOnlyCollection <Expression>(cr[0, -1]));
                    }
                }
                expr = new ListInitExpression((NewExpression)rewrittenNew, new TrueReadOnlyCollection <ElementInit>(newInits));
                break;

            case RewriteAction.SpillStack:
                bool isRefNew = IsRefInstance(node.NewExpression);

                var comma = new ArrayBuilder <Expression>(count + 2 + (isRefNew ? 1 : 0));

                ParameterExpression tempNew = MakeTemp(rewrittenNew.Type);
                comma.UncheckedAdd(new AssignBinaryExpression(tempNew, rewrittenNew));

                ParameterExpression refTempNew = tempNew;
                if (isRefNew)
                {
                    refTempNew = MakeTemp(tempNew.Type.MakeByRefType());
                    comma.UncheckedAdd(new ByRefAssignBinaryExpression(refTempNew, tempNew));
                }

                for (int i = 0; i < count; i++)
                {
                    ChildRewriter cr  = cloneCrs[i];
                    Result        add = cr.Finish(new InstanceMethodCallExpressionN(inits[i].AddMethod, refTempNew, cr[0, -1]));
                    comma.UncheckedAdd(add.Node);
                }

                comma.UncheckedAdd(tempNew);

                expr = MakeBlock(comma);
                break;

            default:
                throw ContractUtils.Unreachable;
            }

            return(new Result(action, expr));
        }
コード例 #7
0
ファイル: CompilerScope.cs プロジェクト: AtsushiKan/corefx
        internal void EmitVariableAccess(LambdaCompiler lc, ReadOnlyCollection<ParameterExpression> vars)
        {
            if (NearestHoistedLocals != null && vars.Count > 0)
            {
                // Find what array each variable is on & its index
                var indexes = new ArrayBuilder<long>(vars.Count);

                foreach (ParameterExpression variable in vars)
                {
                    // For each variable, find what array it's defined on
                    ulong parents = 0;
                    HoistedLocals locals = NearestHoistedLocals;
                    while (!locals.Indexes.ContainsKey(variable))
                    {
                        parents++;
                        locals = locals.Parent;
                        Debug.Assert(locals != null);
                    }

                    // combine the number of parents we walked, with the
                    // real index of variable to get the index to emit.
                    ulong index = (parents << 32) | (uint)locals.Indexes[variable];

                    indexes.UncheckedAdd((long)index);
                }

                EmitGet(NearestHoistedLocals.SelfVariable);
                lc.EmitConstantArray(indexes.ToArray());
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables_ObjectArray_Int64Array);
            }
            else
            {
                // No visible variables
                lc.IL.Emit(OpCodes.Call, RuntimeOps_CreateRuntimeVariables);
            }
        }
コード例 #8
0
        private bool TryEmitHashtableSwitch(SwitchExpression node, CompilationFlags flags)
        {
            // If we have a comparison other than string equality, bail
            MethodInfo equality = String_op_Equality_String_String;
            if (equality != null && !equality.IsStatic)
            {
                equality = null;
            }

            if (node.Comparison != equality)
            {
                return false;
            }

            // All test values must be constant.
            int tests = 0;
            foreach (SwitchCase c in node.Cases)
            {
                foreach (Expression t in c.TestValues)
                {
                    if (!(t is ConstantExpression))
                    {
                        return false;
                    }
                    tests++;
                }
            }

            // Must have >= 7 labels for it to be worth it.
            if (tests < 7)
            {
                return false;
            }

            // If we're in a DynamicMethod, we could just build the dictionary
            // immediately. But that would cause the two code paths to be more
            // different than they really need to be.
            var initializers = new List<ElementInit>(tests);
            var cases = new ArrayBuilder<SwitchCase>(node.Cases.Count);

            int nullCase = -1;
            MethodInfo add = DictionaryOfStringInt32_Add_String_Int32;
            for (int i = 0, n = node.Cases.Count; i < n; i++)
            {
                foreach (ConstantExpression t in node.Cases[i].TestValues)
                {
                    if (t.Value != null)
                    {
                        initializers.Add(Expression.ElementInit(add, new TrueReadOnlyCollection<Expression>(t, Utils.Constant(i))));
                    }
                    else
                    {
                        nullCase = i;
                    }
                }
                cases.UncheckedAdd(Expression.SwitchCase(node.Cases[i].Body, new TrueReadOnlyCollection<Expression>(Utils.Constant(i))));
            }

            // Create the field to hold the lazily initialized dictionary
            MemberExpression dictField = CreateLazyInitializedField<Dictionary<string, int>>("dictionarySwitch");

            // If we happen to initialize it twice (multithreaded case), it's
            // not the end of the world. The C# compiler does better here by
            // emitting a volatile access to the field.
            Expression dictInit = Expression.Condition(
                Expression.Equal(dictField, Expression.Constant(null, dictField.Type)),
                Expression.Assign(
                    dictField,
                    Expression.ListInit(
                        Expression.New(
                            DictionaryOfStringInt32_Ctor_Int32,
                            new TrueReadOnlyCollection<Expression>(
                                Utils.Constant(initializers.Count)
                            )
                        ),
                        initializers
                    )
                ),
                dictField
            );

            //
            // Create a tree like:
            //
            // switchValue = switchValueExpression;
            // if (switchValue == null) {
            //     switchIndex = nullCase;
            // } else {
            //     if (_dictField == null) {
            //         _dictField = new Dictionary<string, int>(count) { { ... }, ... };
            //     }
            //     if (!_dictField.TryGetValue(switchValue, out switchIndex)) {
            //         switchIndex = -1;
            //     }
            // }
            // switch (switchIndex) {
            //     case 0: ...
            //     case 1: ...
            //     ...
            //     default:
            // }
            //
            ParameterExpression switchValue = Expression.Variable(typeof(string), "switchValue");
            ParameterExpression switchIndex = Expression.Variable(typeof(int), "switchIndex");
            BlockExpression reduced = Expression.Block(
                new TrueReadOnlyCollection<ParameterExpression>(switchIndex, switchValue),
                new TrueReadOnlyCollection<Expression>(
                    Expression.Assign(switchValue, node.SwitchValue),
                    Expression.IfThenElse(
                        Expression.Equal(switchValue, Expression.Constant(null, typeof(string))),
                        Expression.Assign(switchIndex, Utils.Constant(nullCase)),
                        Expression.IfThenElse(
                            Expression.Call(dictInit, "TryGetValue", null, switchValue, switchIndex),
                            Utils.Empty,
                            Expression.Assign(switchIndex, Utils.Constant(-1))
                        )
                    ),
                    Expression.Switch(node.Type, switchIndex, node.DefaultBody, null, cases.ToReadOnly())
                )
            );

            EmitExpression(reduced, flags);
            return true;
        }