The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.IlGen \ OptimizerPatternName

  1. //------------------------------------------------------------------------------
  2. // <copyright file="OptimizerPatterns.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System;
  16. using System.Diagnostics;
  17. using System.Xml.Xsl.Qil;
  18. namespace System.Xml.Xsl.IlGen
  19. {
  20.    
  21.     internal enum OptimizerPatternName
  22.     {
  23.         None,
  24.         DodReverse,
  25.         // (Dod $reverse-axis:*)
  26.         EqualityIndex,
  27.         // ILGen will build an equality index when this pattern is recognized
  28.         FilterAttributeKind,
  29.         // (Filter $iter:(Content *) (IsType $iter Attribute))
  30.         FilterContentKind,
  31.         // (Filter $iter:* (IsType $iter $kind:*))
  32.         FilterElements,
  33.         // (Filter $iter:* (And (IsType $iter Element) (NameOf $iter (LiteralQName * * *))))
  34.         IsDocOrderDistinct,
  35.         // True if the annotated expression always returns nodes in document order, with no duplicates
  36.         IsPositional,
  37.         // True if the annotated iterator should track current position during iteration
  38.         JoinAndDod,
  39.         // (Dod (Loop $path1:* $path2:*)), where $path2.ContextNode = $path1
  40.         MaxPosition,
  41.         // True if the position range of the annoted iterator or length expression has a maximum
  42.         SameDepth,
  43.         // True if the annotated expression always returns nodes at the same depth in the tree
  44.         Step,
  45.         // True if the annotated expression returns nodes from one of the simple axis operators, or from a union of Content operators
  46.         SingleTextRtf,
  47.         // (RtfCtor (TextCtor *) *)
  48.         Axis,
  49.         // (AnyAxis *)
  50.         MaybeSideEffects,
  51.         // True if annotated expression might have side effects
  52.         TailCall,
  53.         // (Invoke * *) True if invocation can be compiled as using .tailcall
  54.         DodMerge
  55.         // (Dod (Loop * (Invoke * *))), where invoked function returns nodes in document order
  56.     }
  57.    
  58.     internal enum OptimizerPatternArgument
  59.     {
  60.         StepNode = 0,
  61.         // Step, QilNode: The QilNode of the inner step expression (Content, DescendantOrSelf, XPathFollowing, Union, etc.)
  62.         StepInput = 1,
  63.         // Step, QilNode: The expression from which navigation begins
  64.         ElementQName = 2,
  65.         // FilterElements, QilLiteral: All but elements of this QName are filtered by FilterElements expression
  66.         KindTestType = 2,
  67.         // FilterContentKind, XmlType: All but nodes of this XmlType are filtered by FilterContentKind expression
  68.         IndexedNodes = 0,
  69.         // EqualityIndex, QilNode: Expression that returns the nodes to be indexed
  70.         KeyExpression = 1,
  71.         // EqualityIndex, QilNode: Expression that returns the keys for the index
  72.         DodStep = 2,
  73.         // JoinAndDod | DodReverse, QilNode: Last step in a JoinAndDod expression, or only step in DodReverse expression
  74.         MaxPosition = 2,
  75.         // MaxPosition, int: Maximum position of the annotated iterator or length expression
  76.         RtfText = 2
  77.         // SingleTextRtf, QilNode: Expression that constructs the text of the simple text Rtf
  78.     }
  79.    
  80.     /// <summary>
  81.     /// As the Qil graph is traversed, patterns are identified. Subtrees that match these patterns are
  82.     /// annotated with this class, which identifies the matching patterns and their arguments.
  83.     /// </summary>
  84.     internal class OptimizerPatterns : IQilAnnotation
  85.     {
  86.         private static readonly int PatternCount = Enum.GetValues(typeof(OptimizerPatternName)).Length;
  87.        
  88.         private int patterns;
  89.         // Set of patterns that the annotated Qil node and its subtree matches
  90.         private bool isReadOnly;
  91.         // True if setters are disabled in the case of singleton OptimizerPatterns
  92.         private object arg0, arg1, arg2;
  93.         // Arguments to the matching patterns
  94.         private static OptimizerPatterns ZeroOrOneDefault;
  95.         private static OptimizerPatterns MaybeManyDefault;
  96.         private static OptimizerPatterns DodDefault;
  97.        
  98.         /// <summary>
  99.         /// Get OptimizerPatterns annotation for the specified node. Lazily create if necessary.
  100.         /// </summary>
  101.         public static OptimizerPatterns Read(QilNode nd)
  102.         {
  103.             XmlILAnnotation ann = nd.Annotation as XmlILAnnotation;
  104.             OptimizerPatterns optPatt = (ann != null) ? ann.Patterns : null;
  105.            
  106.             if (optPatt == null) {
  107.                 if (!nd.XmlType.MaybeMany) {
  108.                     // Expressions with ZeroOrOne cardinality should always report IsDocOrderDistinct and NoContainedNodes
  109.                     if (ZeroOrOneDefault == null) {
  110.                         optPatt = new OptimizerPatterns();
  111.                         optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
  112.                         optPatt.AddPattern(OptimizerPatternName.SameDepth);
  113.                         optPatt.isReadOnly = true;
  114.                        
  115.                         ZeroOrOneDefault = optPatt;
  116.                     }
  117.                     else {
  118.                         optPatt = ZeroOrOneDefault;
  119.                     }
  120.                 }
  121.                 else if (nd.XmlType.IsDod) {
  122.                     if (DodDefault == null) {
  123.                         optPatt = new OptimizerPatterns();
  124.                         optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
  125.                         optPatt.isReadOnly = true;
  126.                        
  127.                         DodDefault = optPatt;
  128.                     }
  129.                     else {
  130.                         optPatt = DodDefault;
  131.                     }
  132.                 }
  133.                 else {
  134.                     if (MaybeManyDefault == null) {
  135.                         optPatt = new OptimizerPatterns();
  136.                         optPatt.isReadOnly = true;
  137.                        
  138.                         MaybeManyDefault = optPatt;
  139.                     }
  140.                     else {
  141.                         optPatt = MaybeManyDefault;
  142.                     }
  143.                 }
  144.             }
  145.            
  146.             return optPatt;
  147.         }
  148.        
  149.         /// <summary>
  150.         /// Create and initialize OptimizerPatterns annotation for the specified node.
  151.         /// </summary>
  152.         public static OptimizerPatterns Write(QilNode nd)
  153.         {
  154.             XmlILAnnotation ann = XmlILAnnotation.Write(nd);
  155.             OptimizerPatterns optPatt = ann.Patterns;
  156.            
  157.             if (optPatt == null || optPatt.isReadOnly) {
  158.                 optPatt = new OptimizerPatterns();
  159.                 ann.Patterns = optPatt;
  160.                
  161.                 if (!nd.XmlType.MaybeMany) {
  162.                     optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
  163.                     optPatt.AddPattern(OptimizerPatternName.SameDepth);
  164.                 }
  165.                 else if (nd.XmlType.IsDod) {
  166.                     optPatt.AddPattern(OptimizerPatternName.IsDocOrderDistinct);
  167.                 }
  168.             }
  169.            
  170.             return optPatt;
  171.         }
  172.        
  173.         /// <summary>
  174.         /// Create and initialize OptimizerPatterns annotation for the specified node.
  175.         /// </summary>
  176.         public static void Inherit(QilNode ndSrc, QilNode ndDst, OptimizerPatternName pattern)
  177.         {
  178.             OptimizerPatterns annSrc = OptimizerPatterns.Read(ndSrc);
  179.            
  180.             if (annSrc.MatchesPattern(pattern)) {
  181.                 OptimizerPatterns annDst = OptimizerPatterns.Write(ndDst);
  182.                 annDst.AddPattern(pattern);
  183.                
  184.                 // Inherit pattern arguments
  185.                 switch (pattern) {
  186.                     case OptimizerPatternName.Step:
  187.                         annDst.AddArgument(OptimizerPatternArgument.StepNode, annSrc.GetArgument(OptimizerPatternArgument.StepNode));
  188.                         annDst.AddArgument(OptimizerPatternArgument.StepInput, annSrc.GetArgument(OptimizerPatternArgument.StepInput));
  189.                         break;
  190.                     case OptimizerPatternName.FilterElements:
  191.                        
  192.                         annDst.AddArgument(OptimizerPatternArgument.ElementQName, annSrc.GetArgument(OptimizerPatternArgument.ElementQName));
  193.                         break;
  194.                     case OptimizerPatternName.FilterContentKind:
  195.                        
  196.                         annDst.AddArgument(OptimizerPatternArgument.KindTestType, annSrc.GetArgument(OptimizerPatternArgument.KindTestType));
  197.                         break;
  198.                     case OptimizerPatternName.EqualityIndex:
  199.                        
  200.                         annDst.AddArgument(OptimizerPatternArgument.IndexedNodes, annSrc.GetArgument(OptimizerPatternArgument.IndexedNodes));
  201.                         annDst.AddArgument(OptimizerPatternArgument.KeyExpression, annSrc.GetArgument(OptimizerPatternArgument.KeyExpression));
  202.                         break;
  203.                     case OptimizerPatternName.DodReverse:
  204.                     case OptimizerPatternName.JoinAndDod:
  205.                        
  206.                         annDst.AddArgument(OptimizerPatternArgument.DodStep, annSrc.GetArgument(OptimizerPatternArgument.DodStep));
  207.                         break;
  208.                     case OptimizerPatternName.MaxPosition:
  209.                        
  210.                         annDst.AddArgument(OptimizerPatternArgument.MaxPosition, annSrc.GetArgument(OptimizerPatternArgument.MaxPosition));
  211.                         break;
  212.                     case OptimizerPatternName.SingleTextRtf:
  213.                        
  214.                         annDst.AddArgument(OptimizerPatternArgument.RtfText, annSrc.GetArgument(OptimizerPatternArgument.RtfText));
  215.                         break;
  216.                 }
  217.             }
  218.         }
  219.        
  220.         /// <summary>
  221.         /// Add an argument to one of the matching patterns.
  222.         /// </summary>
  223.         public void AddArgument(OptimizerPatternArgument argId, object arg)
  224.         {
  225.             Debug.Assert(!this.isReadOnly, "This OptimizerPatterns instance is read-only.");
  226.            
  227.             switch ((int)argId) {
  228.                 case 0:
  229.                     this.arg0 = arg;
  230.                     break;
  231.                 case 1:
  232.                     this.arg1 = arg;
  233.                     break;
  234.                 case 2:
  235.                     this.arg2 = arg;
  236.                     break;
  237.                 default:
  238.                     Debug.Assert(false, "Cannot handle more than 2 arguments.");
  239.                     break;
  240.             }
  241.         }
  242.        
  243.         /// <summary>
  244.         /// Get an argument of one of the matching patterns.
  245.         /// </summary>
  246.         public object GetArgument(OptimizerPatternArgument argNum)
  247.         {
  248.             object arg = null;
  249.            
  250.             switch ((int)argNum) {
  251.                 case 0:
  252.                     arg = this.arg0;
  253.                     break;
  254.                 case 1:
  255.                     arg = this.arg1;
  256.                     break;
  257.                 case 2:
  258.                     arg = this.arg2;
  259.                     break;
  260.             }
  261.            
  262.             Debug.Assert(arg != null, "There is no '" + argNum + "' argument.");
  263.             return arg;
  264.         }
  265.        
  266.         /// <summary>
  267.         /// Add a pattern to the list of patterns that the annotated node matches.
  268.         /// </summary>
  269.         public void AddPattern(OptimizerPatternName pattern)
  270.         {
  271.             Debug.Assert(Enum.IsDefined(typeof(OptimizerPatternName), pattern));
  272.             Debug.Assert((int)pattern < 32);
  273.             Debug.Assert(!this.isReadOnly, "This OptimizerPatterns instance is read-only.");
  274.             this.patterns |= (1 << (int)pattern);
  275.         }
  276.        
  277.         /// <summary>
  278.         /// Return true if the annotated node matches the specified pattern.
  279.         /// </summary>
  280.         public bool MatchesPattern(OptimizerPatternName pattern)
  281.         {
  282.             Debug.Assert(Enum.IsDefined(typeof(OptimizerPatternName), pattern));
  283.             return (this.patterns & (1 << (int)pattern)) != 0;
  284.         }
  285.        
  286.         /// <summary>
  287.         /// Return name of this annotation.
  288.         /// </summary>
  289.         public virtual string Name {
  290.             get { return "Patterns"; }
  291.         }
  292.        
  293.         /// <summary>
  294.         /// Return string representation of this annotation.
  295.         /// </summary>
  296.         public override string ToString()
  297.         {
  298.             string s = "";
  299.            
  300.             for (int pattNum = 0; pattNum < PatternCount; pattNum++) {
  301.                 if (MatchesPattern((OptimizerPatternName)pattNum)) {
  302.                     if (s.Length != 0)
  303.                         s += ", ";
  304.                    
  305.                     s += ((OptimizerPatternName)pattNum).ToString();
  306.                 }
  307.             }
  308.            
  309.             return s;
  310.         }
  311.     }
  312. }

Developer Fusion