PageRenderTime 22ms CodeModel.GetById 11ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_2_0/Src/Microsoft.Scripting.Core/Compiler/StackSpiller.Temps.cs

#
C# | 267 lines | 175 code | 41 blank | 51 comment | 45 complexity | 54af1269291145d34bd2d4e9a8c76965 MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Microsoft Public License. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the  Microsoft Public License, please send an email to 
  8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Microsoft Public License.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15using System; using Microsoft;
 16
 17
 18using System.Collections.Generic;
 19using System.Collections.ObjectModel;
 20using System.Diagnostics;
 21using Microsoft.Scripting.Utils;
 22
 23namespace Microsoft.Linq.Expressions.Compiler {
 24
 25    internal partial class StackSpiller {
 26
 27        private class TempMaker {
 28            /// <summary>
 29            /// Current temporary variable
 30            /// </summary>
 31            private int _temp;
 32
 33            /// <summary>
 34            /// List of free temporary variables. These can be recycled for new temps.
 35            /// </summary>
 36            private List<ParameterExpression> _freeTemps;
 37
 38            /// <summary>
 39            /// Stack of currently active temporary variables.
 40            /// </summary>
 41            private Stack<ParameterExpression> _usedTemps;
 42
 43            /// <summary>
 44            /// List of all temps created by stackspiller for this rule/lambda
 45            /// </summary>
 46            private List<ParameterExpression> _temps = new List<ParameterExpression>();
 47
 48            internal List<ParameterExpression> Temps {
 49                get { return _temps; }
 50            }
 51
 52            internal ParameterExpression Temp(Type type) {
 53                ParameterExpression temp;
 54                if (_freeTemps != null) {
 55                    // Recycle from the free-list if possible.
 56                    for (int i = _freeTemps.Count - 1; i >= 0; i--) {
 57                        temp = _freeTemps[i];
 58                        if (temp.Type == type) {
 59                            _freeTemps.RemoveAt(i);
 60                            return UseTemp(temp);
 61                        }
 62                    }
 63                }
 64                // Not on the free-list, create a brand new one.
 65                temp = Expression.Variable(type, "$temp$" + _temp++);
 66                _temps.Add(temp);
 67                return UseTemp(temp);
 68            }
 69
 70            private ParameterExpression UseTemp(ParameterExpression temp) {
 71                Debug.Assert(_freeTemps == null || !_freeTemps.Contains(temp));
 72                Debug.Assert(_usedTemps == null || !_usedTemps.Contains(temp));
 73
 74                if (_usedTemps == null) {
 75                    _usedTemps = new Stack<ParameterExpression>();
 76                }
 77                _usedTemps.Push(temp);
 78                return temp;
 79            }
 80
 81            private void FreeTemp(ParameterExpression temp) {
 82                Debug.Assert(_freeTemps == null || !_freeTemps.Contains(temp));
 83                if (_freeTemps == null) {
 84                    _freeTemps = new List<ParameterExpression>();
 85                }
 86                _freeTemps.Add(temp);
 87            }
 88
 89            internal int Mark() {
 90                return _usedTemps != null ? _usedTemps.Count : 0;
 91            }
 92
 93            // Free temporaries created since the last marking. 
 94            // This is a performance optimization to lower the overall number of tempories needed.
 95            internal void Free(int mark) {
 96                // (_usedTemps != null) ==> (mark <= _usedTemps.Count)
 97                Debug.Assert(_usedTemps == null || mark <= _usedTemps.Count);
 98                // (_usedTemps == null) ==> (mark == 0)
 99                Debug.Assert(mark == 0 || _usedTemps != null);
100
101                if (_usedTemps != null) {
102                    while (mark < _usedTemps.Count) {
103                        FreeTemp(_usedTemps.Pop());
104                    }
105                }
106            }
107
108            [Conditional("DEBUG")]
109            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
110            internal void VerifyTemps() {
111                Debug.Assert(_usedTemps == null || _usedTemps.Count == 0);
112            }
113        }
114
115
116        /// <summary>
117        /// Rewrites child expressions, spilling them into temps if needed. The
118        /// stack starts in the inital state, and after the first subexpression
119        /// is added it is change to non-empty. This behavior can be overriden
120        /// by setting the stack manually between adds.
121        /// 
122        /// When all children have been added, the caller should rewrite the 
123        /// node if Rewrite is true. Then, it should call crFinish with etiher
124        /// the orignal expression or the rewritten expression. Finish will call
125        /// Expression.Comma if necessary and return a new Result.
126        /// </summary>
127        private class ChildRewriter {
128            private readonly StackSpiller _self;
129            private readonly Expression[] _expressions;
130            private int _expressionsCount;
131            private List<Expression> _comma;
132            private RewriteAction _action;
133            private Stack _stack;
134            private bool _done;
135
136            internal ChildRewriter(StackSpiller self, Stack stack, int count) {
137                _self = self;
138                _stack = stack;
139                _expressions = new Expression[count];
140            }
141
142            internal void Add(Expression node) {
143                Debug.Assert(!_done);
144
145                if (node == null) {
146                    _expressions[_expressionsCount++] = null;
147                    return;
148                }
149
150                Result exp = _self.RewriteExpression(node, _stack);
151                _action |= exp.Action;
152                _stack = Stack.NonEmpty;
153
154                // track items in case we need to copy or spill stack
155                _expressions[_expressionsCount++] = exp.Node;
156            }
157
158            internal void Add(IList<Expression> expressions) {
159                for (int i = 0, count = expressions.Count; i < count; i++) {
160                    Add(expressions[i]);
161                }
162            }
163
164            private void EnsureDone() {
165                // done adding arguments, build the comma if necessary
166                if (!_done) {
167                    _done = true;
168
169                    if (_action == RewriteAction.SpillStack) {
170                        Expression[] clone = _expressions;
171                        int count = clone.Length;
172                        List<Expression> comma = new List<Expression>(count + 1);
173                        for (int i = 0; i < count; i++) {
174                            if (clone[i] != null) {
175                                Expression temp;
176                                clone[i] = _self.ToTemp(clone[i], out temp);
177                                comma.Add(temp);
178                            }
179                        }
180                        comma.Capacity = comma.Count + 1;
181                        _comma = comma;
182                    }
183                }
184            }
185
186            internal bool Rewrite {
187                get { return _action != RewriteAction.None; }
188            }
189
190            internal RewriteAction Action {
191                get { return _action; }
192            }
193
194            internal Result Finish(Expression expr) {
195                EnsureDone();
196
197                if (_action == RewriteAction.SpillStack) {
198                    Debug.Assert(_comma.Capacity == _comma.Count + 1);
199                    _comma.Add(expr);
200                    expr = Expression.Comma(new ReadOnlyCollection<Expression>(_comma));
201                }
202
203                return new Result(_action, expr);
204            }
205
206            internal Expression this[int index] {
207                get {
208                    EnsureDone();
209                    if (index < 0) {
210                        index += _expressions.Length;
211                    }
212                    return _expressions[index];
213                }
214            }
215            internal ReadOnlyCollection<Expression> this[int first, int last] {
216                get {
217                    EnsureDone();
218                    if (last < 0) {
219                        last += _expressions.Length;
220                    }
221                    int count = last - first + 1;
222                    ContractUtils.RequiresArrayRange(_expressions, first, count, "first", "last");
223
224                    if (count == _expressions.Length) {
225                        Debug.Assert(first == 0);
226                        // if the entire array is requested just return it so we don't make a new array
227                        return new ReadOnlyCollection<Expression>(_expressions);
228                    }
229
230                    Expression[] clone = new Expression[count];
231                    Array.Copy(_expressions, first, clone, 0, count);
232                    return new ReadOnlyCollection<Expression>(clone);
233                }
234            }
235        }
236
237
238        private ParameterExpression MakeTemp(Type type) {
239            return _tm.Temp(type);
240        }
241
242        private int Mark() {
243            return _tm.Mark();
244        }
245
246        private void Free(int mark) {
247            _tm.Free(mark);
248        }
249
250        [Conditional("DEBUG")]
251        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
252        private void VerifyTemps() {
253            _tm.VerifyTemps();
254        }
255
256        /// <summary>
257        /// Will perform:
258        ///     save: temp = expression
259        ///     return value: temp
260        /// </summary>
261        private ParameterExpression ToTemp(Expression expression, out Expression save) {
262            ParameterExpression temp = MakeTemp(expression.Type);
263            save = Expression.Assign(temp, expression);
264            return temp;
265        }
266    }
267}