File: XmlIlTrace.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (195 lines) | stat: -rw-r--r-- 7,597 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
//------------------------------------------------------------------------------
// <copyright file="XmlILTrace.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
// <owner current="true" primary="true">akimball</owner>
//------------------------------------------------------------------------------
using System;
using System.IO;
using System.Security;
using System.Xml;
using System.Globalization;
using System.Xml.Xsl.Qil;
using System.Runtime.Versioning;

// This class is only for debug purposes so there is no need to have it in Retail builds
#if DEBUG
namespace System.Xml.Xsl.IlGen {
    /// <summary>
    /// Helper class that facilitates tracing of ILGen.
    /// </summary>
    internal static class XmlILTrace {
        private const int MAX_REWRITES = 200;

        /// <summary>
        /// Check environment variable in order to determine whether to write out trace files.  This really should be a
        /// check of the configuration file, but System.Xml does not yet have a good tracing story.
        /// </summary>
        private static volatile string dirName = null;
        private static volatile bool alreadyCheckedEnabled = false;

        /// <summary>
        /// True if tracing has been enabled (environment variable set).
        /// </summary>
        public static bool IsEnabled {

            // SxS: This property poses potential SxS issue. However the class is used only in debug builds (it won't 
            // get compiled into ret build) so it's OK to suppress the SxS warning.
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            [ResourceExposure(ResourceScope.None)]
            get {
                // If environment variable has not yet been checked, do so now
                if (!alreadyCheckedEnabled) {
                    try {
                        dirName = Environment.GetEnvironmentVariable("XmlILTrace");
                    }
                    catch (SecurityException) {
                        // If user does not have access to environment variables, tracing will remain disabled
                    }

                    alreadyCheckedEnabled = true;
                }

                return (dirName != null);
            }
        }

        /// <summary>
        /// If tracing is enabled, this method will delete the contents of "filename" in preparation for append
        /// operations.
        /// </summary>
        [ResourceConsumption(ResourceScope.Machine)]
        [ResourceExposure(ResourceScope.Machine)]
        public static void PrepareTraceWriter(string fileName) {
            if (!IsEnabled)
                return;

            File.Delete(dirName + "\\" + fileName);
        }

        /// <summary>
        /// If tracing is enabled, this method will open a TextWriter over "fileName" and return it.  Otherwise,
        /// null will be returned.
        /// </summary>
        [ResourceConsumption(ResourceScope.Machine)]
        [ResourceExposure(ResourceScope.Machine)]
        public static TextWriter GetTraceWriter(string fileName) {
            if (!IsEnabled)
                return null;

            return new StreamWriter(dirName + "\\" + fileName, true);
        }

        /// <summary>
        /// Serialize Qil tree to "fileName", in the directory identified by "dirName".
        /// </summary>
        [ResourceConsumption(ResourceScope.Machine)]
        [ResourceExposure(ResourceScope.Machine)]
        public static void WriteQil(QilExpression qil, string fileName) {
            if (!IsEnabled)
                return;

            XmlWriter w = XmlWriter.Create(dirName + "\\" + fileName);
            try {
                WriteQil(qil, w);
            }
            finally {
                w.Close();
            }
        }

        /// <summary>
        /// Trace ILGen optimizations and log them to "fileName".
        /// </summary>
        [ResourceConsumption(ResourceScope.Machine)]
        [ResourceExposure(ResourceScope.Machine)]
        public static void TraceOptimizations(QilExpression qil, string fileName) {
            if (!IsEnabled)
                return;

            XmlWriter w = XmlWriter.Create(dirName + "\\" + fileName);

            w.WriteStartDocument();
            w.WriteProcessingInstruction("xml-stylesheet", "href='qilo.xslt' type='text/xsl'");
            w.WriteStartElement("QilOptimizer");
            w.WriteAttributeString("timestamp", DateTime.Now.ToString(CultureInfo.InvariantCulture));
            WriteQilRewrite(qil, w, null);

            try {
                // Then, rewrite the graph until "done" or some max value is reached.
                for (int i = 1; i < MAX_REWRITES; i++) {
                    QilExpression qilTemp = (QilExpression) (new QilCloneVisitor(qil.Factory).Clone(qil));

                    XmlILOptimizerVisitor visitor = new XmlILOptimizerVisitor(qilTemp, !qilTemp.IsDebug);
                    visitor.Threshold = i;
                    qilTemp = visitor.Optimize();

                    // In debug code, ensure that QIL after N steps is correct
                    QilValidationVisitor.Validate(qilTemp);

                    // Trace the rewrite
                    WriteQilRewrite(qilTemp, w, OptimizationToString(visitor.LastReplacement));

                    if (visitor.ReplacementCount < i)
                        break;
                }
            }
            catch (Exception e) {
                if (!XmlException.IsCatchableException(e)) {
                    throw;
                }
                w.WriteElementString("Exception", null, e.ToString());
                throw;
            }
            finally {
                w.WriteEndElement();
                w.WriteEndDocument();
                w.Flush();
                w.Close();
            }
        }

        /// <summary>
        /// Serialize Qil tree to writer "w".
        /// </summary>
        private static void WriteQil(QilExpression qil, XmlWriter w) {
            QilXmlWriter qw = new QilXmlWriter(w);
            qw.ToXml(qil);
        }

        /// <summary>
        /// Serialize rewritten Qil tree to writer "w".
        /// </summary>
        private static void WriteQilRewrite(QilExpression qil, XmlWriter w, string rewriteName) {
            w.WriteStartElement("Diff");
            if (rewriteName != null)
                w.WriteAttributeString("rewrite", rewriteName);
            WriteQil(qil, w);
            w.WriteEndElement();
        }

        /// <summary>
        /// Get friendly string description of an ILGen optimization.
        /// </summary>
        private static string OptimizationToString(int opt) {
            string s = Enum.GetName(typeof(XmlILOptimization), opt);
            if (s.StartsWith("Introduce", StringComparison.Ordinal)) {
                return s.Substring(9) + " introduction";
            }
            else if (s.StartsWith("Eliminate", StringComparison.Ordinal)) {
                return s.Substring(9) + " elimination";
            }
            else if (s.StartsWith("Commute", StringComparison.Ordinal)) {
                return s.Substring(7) + " commutation";
            }
            else if (s.StartsWith("Fold", StringComparison.Ordinal)) {
                return s.Substring(4) + " folding";
            }
            else if (s.StartsWith("Misc", StringComparison.Ordinal)) {
                return s.Substring(4);
            }
            return s;
        }
    }
}
#endif