/IronPython_2_0/Src/Microsoft.Scripting/Generation/GlobalOptimizedRewriter.cs

# · C# · 125 lines · 82 code · 24 blank · 19 comment · 11 complexity · 8b0731acce905e3b780191f8fb9b1c75 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. * ***************************************************************************/
  15. using System; using Microsoft;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using Microsoft.Linq.Expressions;
  19. using System.Reflection;
  20. using System.Reflection.Emit;
  21. using Microsoft.Scripting.Ast;
  22. using Microsoft.Scripting.Runtime;
  23. namespace Microsoft.Scripting.Generation {
  24. internal abstract class GlobalOptimizedRewriter : GlobalRewriter {
  25. private readonly Dictionary<GlobalVariableExpression, Expression> _mapToExpression = new Dictionary<GlobalVariableExpression, Expression>();
  26. private readonly Dictionary<string, GlobalVariableExpression> _globalNames = new Dictionary<string, GlobalVariableExpression>();
  27. internal GlobalOptimizedRewriter() {
  28. _indirectSymbolIds = new Dictionary<SymbolId, FieldBuilder>();
  29. }
  30. internal GlobalOptimizedRewriter(Dictionary<SymbolId, FieldBuilder> symbolDict) {
  31. _indirectSymbolIds = symbolDict;
  32. }
  33. protected abstract Expression MakeWrapper(GlobalVariableExpression variable);
  34. protected override Expression RewriteGet(GlobalVariableExpression node) {
  35. return Expression.ConvertHelper(MapToExpression(node), node.Type);
  36. }
  37. protected override Expression RewriteSet(AssignmentExpression node) {
  38. GlobalVariableExpression lvalue = (GlobalVariableExpression)node.Expression;
  39. return Expression.ConvertHelper(
  40. Expression.Assign(
  41. MapToExpression(lvalue),
  42. Expression.ConvertHelper(Visit(node.Value), typeof(object)),
  43. node.Annotations
  44. ),
  45. node.Type
  46. );
  47. }
  48. protected Expression MapToExpression(GlobalVariableExpression variable) {
  49. Expression result;
  50. if (_mapToExpression.TryGetValue(variable, out result)) {
  51. return result;
  52. }
  53. EnsureUniqueName(_globalNames, variable);
  54. result = Expression.Property(
  55. MakeWrapper(variable),
  56. typeof(ModuleGlobalWrapper).GetProperty("CurrentValue"),
  57. variable.Annotations
  58. );
  59. return _mapToExpression[variable] = result;
  60. }
  61. // TODO: Do we really need this optimization?
  62. // it adds complexity
  63. #region SymbolId rewrite support
  64. // TypeGen, possibly null
  65. protected TypeGen TypeGen { get; set; }
  66. // If TypeGen is non-null, we rewrite SymbolIds to static field accesses
  67. private readonly Dictionary<SymbolId, FieldBuilder> _indirectSymbolIds;
  68. protected override Expression VisitExtension(Expression node) {
  69. var symbol = node as SymbolConstantExpression;
  70. if (symbol != null && TypeGen != null) {
  71. return GetSymbolExpression(symbol.Value);
  72. }
  73. return base.VisitExtension(node);
  74. }
  75. protected void EmitSymbolId(ILGen cg, SymbolId id) {
  76. cg.Emit(OpCodes.Ldsfld, GetSymbolField(id));
  77. }
  78. private Expression GetSymbolExpression(SymbolId id) {
  79. return Expression.Field(null, GetSymbolField(id));
  80. }
  81. private FieldInfo GetSymbolField(SymbolId id) {
  82. Debug.Assert(TypeGen != null);
  83. if (id == SymbolId.Empty) {
  84. return typeof(SymbolId).GetField("Empty");
  85. }
  86. FieldBuilder value;
  87. if (!_indirectSymbolIds.TryGetValue(id, out value)) {
  88. // create field, emit fix-up...
  89. value = TypeGen.AddStaticField(typeof(SymbolId), FieldAttributes.Public, SymbolTable.IdToString(id));
  90. ILGen init = TypeGen.TypeInitializer;
  91. if (_indirectSymbolIds.Count == 0) {
  92. init.EmitType(TypeGen.TypeBuilder);
  93. init.EmitCall(typeof(RuntimeHelpers), "InitializeSymbols");
  94. }
  95. _indirectSymbolIds[id] = value;
  96. }
  97. return value;
  98. }
  99. #endregion
  100. }
  101. }