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 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
|
//------------------------------------------------------------------------------
// <copyright file="OptimizerPatterns.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Xml.Xsl.Qil;
namespace System.Xml.Xsl.IlGen {
internal enum OptimizerPatternName {
None,
DodReverse, // (Dod $reverse-axis:*)
EqualityIndex, // ILGen will build an equality index when this pattern is recognized
FilterAttributeKind, // (Filter $iter:(Content *) (IsType $iter Attribute))
FilterContentKind, // (Filter $iter:* (IsType $iter $kind:*))
FilterElements, // (Filter $iter:* (And (IsType $iter Element) (NameOf $iter (LiteralQName * * *))))
IsDocOrderDistinct, // True if the annotated expression always returns nodes in document order, with no duplicates
IsPositional, // True if the annotated iterator should track current position during iteration
JoinAndDod, // (Dod (Loop $path1:* $path2:*)), where $path2.ContextNode = $path1
MaxPosition, // True if the position range of the annoted iterator or length expression has a maximum
SameDepth, // True if the annotated expression always returns nodes at the same depth in the tree
Step, // True if the annotated expression returns nodes from one of the simple axis operators, or from a union of Content operators
SingleTextRtf, // (RtfCtor (TextCtor *) *)
Axis, // (AnyAxis *)
MaybeSideEffects, // True if annotated expression might have side effects
TailCall, // (Invoke * *) True if invocation can be compiled as using .tailcall
DodMerge, // (Dod (Loop * (Invoke * *))), where invoked function returns nodes in document order
IsReferenced, // True if the annotated global iterator is referenced at least once
}
internal enum OptimizerPatternArgument {
StepNode = 0, // Step, QilNode: The QilNode of the inner step expression (Content, DescendantOrSelf, XPathFollowing, Union, etc.)
StepInput = 1, // Step, QilNode: The expression from which navigation begins
ElementQName = 2, // FilterElements, QilLiteral: All but elements of this QName are filtered by FilterElements expression
KindTestType = 2, // FilterContentKind, XmlType: All but nodes of this XmlType are filtered by FilterContentKind expression
IndexedNodes = 0, // EqualityIndex, QilNode: Expression that returns the nodes to be indexed
KeyExpression = 1, // EqualityIndex, QilNode: Expression that returns the keys for the index
DodStep = 2, // JoinAndDod | DodReverse, QilNode: Last step in a JoinAndDod expression, or only step in DodReverse expression
MaxPosition = 2, // MaxPosition, int: Maximum position of the annotated iterator or length expression
RtfText = 2, // SingleTextRtf, QilNode: Expression that constructs the text of the simple text Rtf
}
/// <summary>
/// As the Qil graph is traversed, patterns are identified. Subtrees that match these patterns are
/// annotated with this class, which identifies the matching patterns and their arguments.
/// </summary>
internal class OptimizerPatterns : IQilAnnotation {
private static readonly int PatternCount = Enum.GetValues(typeof(OptimizerPatternName)).Length;
private int patterns; // Set of patterns that the annotated Qil node and its subtree matches
private bool isReadOnly; // True if setters are disabled in the case of singleton OptimizerPatterns
private object arg0, arg1, arg2; // Arguments to the matching patterns
private static volatile OptimizerPatterns ZeroOrOneDefault;
private static volatile OptimizerPatterns MaybeManyDefault;
private static volatile OptimizerPatterns DodDefault;
/// <summary>
/// Get OptimizerPatterns annotation for the specified node. Lazily create if necessary.
/// </summary>
public static OptimizerPatterns Read(QilNode nd) {
XmlILAnnotation ann = nd.Annotation as XmlILAnnotation;
OptimizerPatterns optPatt = (ann != null) ? ann.Patterns : null;
if (optPatt == null) {
if (!nd.XmlType.MaybeMany) {
// Expressions with ZeroOrOne cardinality should always report IsDocOrderDistinct and NoContainedNodes
if (ZeroOrOneDefault == null) {
optPatt = new OptimizerPatterns();
optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
optPatt.AddPattern(OptimizerPatternName.SameDepth);
optPatt.isReadOnly = true;
ZeroOrOneDefault = optPatt;
}
else {
optPatt = ZeroOrOneDefault;
}
}
else if (nd.XmlType.IsDod) {
if (DodDefault == null) {
optPatt = new OptimizerPatterns();
optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
optPatt.isReadOnly = true;
DodDefault = optPatt;
}
else {
optPatt = DodDefault;
}
}
else {
if (MaybeManyDefault == null) {
optPatt = new OptimizerPatterns();
optPatt.isReadOnly = true;
MaybeManyDefault = optPatt;
}
else {
optPatt = MaybeManyDefault;
}
}
}
return optPatt;
}
/// <summary>
/// Create and initialize OptimizerPatterns annotation for the specified node.
/// </summary>
public static OptimizerPatterns Write(QilNode nd) {
XmlILAnnotation ann = XmlILAnnotation.Write(nd);
OptimizerPatterns optPatt = ann.Patterns;
if (optPatt == null || optPatt.isReadOnly) {
optPatt = new OptimizerPatterns();
ann.Patterns = optPatt;
if (!nd.XmlType.MaybeMany) {
optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
optPatt.AddPattern(OptimizerPatternName.SameDepth);
}
else if (nd.XmlType.IsDod) {
optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
}
}
return optPatt;
}
/// <summary>
/// Create and initialize OptimizerPatterns annotation for the specified node.
/// </summary>
public static void Inherit(QilNode ndSrc, QilNode ndDst, OptimizerPatternName pattern) {
OptimizerPatterns annSrc = OptimizerPatterns.Read(ndSrc);
if (annSrc.MatchesPattern(pattern)) {
OptimizerPatterns annDst = OptimizerPatterns.Write(ndDst);
annDst.AddPattern(pattern);
// Inherit pattern arguments
switch (pattern) {
case OptimizerPatternName.Step:
annDst.AddArgument(OptimizerPatternArgument.StepNode, annSrc.GetArgument(OptimizerPatternArgument.StepNode));
annDst.AddArgument(OptimizerPatternArgument.StepInput, annSrc.GetArgument(OptimizerPatternArgument.StepInput));
break;
case OptimizerPatternName.FilterElements:
annDst.AddArgument(OptimizerPatternArgument.ElementQName, annSrc.GetArgument(OptimizerPatternArgument.ElementQName));
break;
case OptimizerPatternName.FilterContentKind:
annDst.AddArgument(OptimizerPatternArgument.KindTestType, annSrc.GetArgument(OptimizerPatternArgument.KindTestType));
break;
case OptimizerPatternName.EqualityIndex:
annDst.AddArgument(OptimizerPatternArgument.IndexedNodes, annSrc.GetArgument(OptimizerPatternArgument.IndexedNodes));
annDst.AddArgument(OptimizerPatternArgument.KeyExpression, annSrc.GetArgument(OptimizerPatternArgument.KeyExpression));
break;
case OptimizerPatternName.DodReverse:
case OptimizerPatternName.JoinAndDod:
annDst.AddArgument(OptimizerPatternArgument.DodStep, annSrc.GetArgument(OptimizerPatternArgument.DodStep));
break;
case OptimizerPatternName.MaxPosition:
annDst.AddArgument(OptimizerPatternArgument.MaxPosition, annSrc.GetArgument(OptimizerPatternArgument.MaxPosition));
break;
case OptimizerPatternName.SingleTextRtf:
annDst.AddArgument(OptimizerPatternArgument.RtfText, annSrc.GetArgument(OptimizerPatternArgument.RtfText));
break;
}
}
}
/// <summary>
/// Add an argument to one of the matching patterns.
/// </summary>
public void AddArgument(OptimizerPatternArgument argId, object arg) {
Debug.Assert(!this.isReadOnly, "This OptimizerPatterns instance is read-only.");
switch ((int) argId) {
case 0: this.arg0 = arg; break;
case 1: this.arg1 = arg; break;
case 2: this.arg2 = arg; break;
default:
Debug.Assert(false, "Cannot handle more than 2 arguments.");
break;
}
}
/// <summary>
/// Get an argument of one of the matching patterns.
/// </summary>
public object GetArgument(OptimizerPatternArgument argNum) {
object arg = null;
switch ((int) argNum) {
case 0: arg = this.arg0; break;
case 1: arg = this.arg1; break;
case 2: arg = this.arg2; break;
}
Debug.Assert(arg != null, "There is no '" + argNum + "' argument.");
return arg;
}
/// <summary>
/// Add a pattern to the list of patterns that the annotated node matches.
/// </summary>
public void AddPattern(OptimizerPatternName pattern) {
Debug.Assert(Enum.IsDefined(typeof(OptimizerPatternName), pattern));
Debug.Assert((int) pattern < 32);
Debug.Assert(!this.isReadOnly, "This OptimizerPatterns instance is read-only.");
this.patterns |= (1 << (int) pattern);
}
/// <summary>
/// Return true if the annotated node matches the specified pattern.
/// </summary>
public bool MatchesPattern(OptimizerPatternName pattern) {
Debug.Assert(Enum.IsDefined(typeof(OptimizerPatternName), pattern));
return (this.patterns & (1 << (int) pattern)) != 0;
}
/// <summary>
/// Return name of this annotation.
/// </summary>
public virtual string Name {
get { return "Patterns"; }
}
/// <summary>
/// Return string representation of this annotation.
/// </summary>
public override string ToString() {
string s = "";
for (int pattNum = 0; pattNum < PatternCount; pattNum++) {
if (MatchesPattern((OptimizerPatternName) pattNum)) {
if (s.Length != 0)
s += ", ";
s += ((OptimizerPatternName) pattNum).ToString();
}
}
return s;
}
}
}
|