PageRenderTime 46ms CodeModel.GetById 20ms 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
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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. * ***************************************************************************/
  15. using System; using Microsoft;
  16. using System.Collections.Generic;
  17. using System.Collections.ObjectModel;
  18. using System.Diagnostics;
  19. using Microsoft.Scripting.Utils;
  20. namespace Microsoft.Linq.Expressions.Compiler {
  21. internal partial class StackSpiller {
  22. private class TempMaker {
  23. /// <summary>
  24. /// Current temporary variable
  25. /// </summary>
  26. private int _temp;
  27. /// <summary>
  28. /// List of free temporary variables. These can be recycled for new temps.
  29. /// </summary>
  30. private List<ParameterExpression> _freeTemps;
  31. /// <summary>
  32. /// Stack of currently active temporary variables.
  33. /// </summary>
  34. private Stack<ParameterExpression> _usedTemps;
  35. /// <summary>
  36. /// List of all temps created by stackspiller for this rule/lambda
  37. /// </summary>
  38. private List<ParameterExpression> _temps = new List<ParameterExpression>();
  39. internal List<ParameterExpression> Temps {
  40. get { return _temps; }
  41. }
  42. internal ParameterExpression Temp(Type type) {
  43. ParameterExpression temp;
  44. if (_freeTemps != null) {
  45. // Recycle from the free-list if possible.
  46. for (int i = _freeTemps.Count - 1; i >= 0; i--) {
  47. temp = _freeTemps[i];
  48. if (temp.Type == type) {
  49. _freeTemps.RemoveAt(i);
  50. return UseTemp(temp);
  51. }
  52. }
  53. }
  54. // Not on the free-list, create a brand new one.
  55. temp = Expression.Variable(type, "$temp$" + _temp++);
  56. _temps.Add(temp);
  57. return UseTemp(temp);
  58. }
  59. private ParameterExpression UseTemp(ParameterExpression temp) {
  60. Debug.Assert(_freeTemps == null || !_freeTemps.Contains(temp));
  61. Debug.Assert(_usedTemps == null || !_usedTemps.Contains(temp));
  62. if (_usedTemps == null) {
  63. _usedTemps = new Stack<ParameterExpression>();
  64. }
  65. _usedTemps.Push(temp);
  66. return temp;
  67. }
  68. private void FreeTemp(ParameterExpression temp) {
  69. Debug.Assert(_freeTemps == null || !_freeTemps.Contains(temp));
  70. if (_freeTemps == null) {
  71. _freeTemps = new List<ParameterExpression>();
  72. }
  73. _freeTemps.Add(temp);
  74. }
  75. internal int Mark() {
  76. return _usedTemps != null ? _usedTemps.Count : 0;
  77. }
  78. // Free temporaries created since the last marking.
  79. // This is a performance optimization to lower the overall number of tempories needed.
  80. internal void Free(int mark) {
  81. // (_usedTemps != null) ==> (mark <= _usedTemps.Count)
  82. Debug.Assert(_usedTemps == null || mark <= _usedTemps.Count);
  83. // (_usedTemps == null) ==> (mark == 0)
  84. Debug.Assert(mark == 0 || _usedTemps != null);
  85. if (_usedTemps != null) {
  86. while (mark < _usedTemps.Count) {
  87. FreeTemp(_usedTemps.Pop());
  88. }
  89. }
  90. }
  91. [Conditional("DEBUG")]
  92. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  93. internal void VerifyTemps() {
  94. Debug.Assert(_usedTemps == null || _usedTemps.Count == 0);
  95. }
  96. }
  97. /// <summary>
  98. /// Rewrites child expressions, spilling them into temps if needed. The
  99. /// stack starts in the inital state, and after the first subexpression
  100. /// is added it is change to non-empty. This behavior can be overriden
  101. /// by setting the stack manually between adds.
  102. ///
  103. /// When all children have been added, the caller should rewrite the
  104. /// node if Rewrite is true. Then, it should call crFinish with etiher
  105. /// the orignal expression or the rewritten expression. Finish will call
  106. /// Expression.Comma if necessary and return a new Result.
  107. /// </summary>
  108. private class ChildRewriter {
  109. private readonly StackSpiller _self;
  110. private readonly Expression[] _expressions;
  111. private int _expressionsCount;
  112. private List<Expression> _comma;
  113. private RewriteAction _action;
  114. private Stack _stack;
  115. private bool _done;
  116. internal ChildRewriter(StackSpiller self, Stack stack, int count) {
  117. _self = self;
  118. _stack = stack;
  119. _expressions = new Expression[count];
  120. }
  121. internal void Add(Expression node) {
  122. Debug.Assert(!_done);
  123. if (node == null) {
  124. _expressions[_expressionsCount++] = null;
  125. return;
  126. }
  127. Result exp = _self.RewriteExpression(node, _stack);
  128. _action |= exp.Action;
  129. _stack = Stack.NonEmpty;
  130. // track items in case we need to copy or spill stack
  131. _expressions[_expressionsCount++] = exp.Node;
  132. }
  133. internal void Add(IList<Expression> expressions) {
  134. for (int i = 0, count = expressions.Count; i < count; i++) {
  135. Add(expressions[i]);
  136. }
  137. }
  138. private void EnsureDone() {
  139. // done adding arguments, build the comma if necessary
  140. if (!_done) {
  141. _done = true;
  142. if (_action == RewriteAction.SpillStack) {
  143. Expression[] clone = _expressions;
  144. int count = clone.Length;
  145. List<Expression> comma = new List<Expression>(count + 1);
  146. for (int i = 0; i < count; i++) {
  147. if (clone[i] != null) {
  148. Expression temp;
  149. clone[i] = _self.ToTemp(clone[i], out temp);
  150. comma.Add(temp);
  151. }
  152. }
  153. comma.Capacity = comma.Count + 1;
  154. _comma = comma;
  155. }
  156. }
  157. }
  158. internal bool Rewrite {
  159. get { return _action != RewriteAction.None; }
  160. }
  161. internal RewriteAction Action {
  162. get { return _action; }
  163. }
  164. internal Result Finish(Expression expr) {
  165. EnsureDone();
  166. if (_action == RewriteAction.SpillStack) {
  167. Debug.Assert(_comma.Capacity == _comma.Count + 1);
  168. _comma.Add(expr);
  169. expr = Expression.Comma(new ReadOnlyCollection<Expression>(_comma));
  170. }
  171. return new Result(_action, expr);
  172. }
  173. internal Expression this[int index] {
  174. get {
  175. EnsureDone();
  176. if (index < 0) {
  177. index += _expressions.Length;
  178. }
  179. return _expressions[index];
  180. }
  181. }
  182. internal ReadOnlyCollection<Expression> this[int first, int last] {
  183. get {
  184. EnsureDone();
  185. if (last < 0) {
  186. last += _expressions.Length;
  187. }
  188. int count = last - first + 1;
  189. ContractUtils.RequiresArrayRange(_expressions, first, count, "first", "last");
  190. if (count == _expressions.Length) {
  191. Debug.Assert(first == 0);
  192. // if the entire array is requested just return it so we don't make a new array
  193. return new ReadOnlyCollection<Expression>(_expressions);
  194. }
  195. Expression[] clone = new Expression[count];
  196. Array.Copy(_expressions, first, clone, 0, count);
  197. return new ReadOnlyCollection<Expression>(clone);
  198. }
  199. }
  200. }
  201. private ParameterExpression MakeTemp(Type type) {
  202. return _tm.Temp(type);
  203. }
  204. private int Mark() {
  205. return _tm.Mark();
  206. }
  207. private void Free(int mark) {
  208. _tm.Free(mark);
  209. }
  210. [Conditional("DEBUG")]
  211. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
  212. private void VerifyTemps() {
  213. _tm.VerifyTemps();
  214. }
  215. /// <summary>
  216. /// Will perform:
  217. /// save: temp = expression
  218. /// return value: temp
  219. /// </summary>
  220. private ParameterExpression ToTemp(Expression expression, out Expression save) {
  221. ParameterExpression temp = MakeTemp(expression.Type);
  222. save = Expression.Assign(temp, expression);
  223. return temp;
  224. }
  225. }
  226. }