PageRenderTime 13ms CodeModel.GetById 2ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

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