| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Dispatcher
- {
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Xml.XPath;
- internal class SubExpr
- {
- internal int var;
- internal int refCount; // opcodes
- internal bool useSpecial;
- Opcode ops;
- SubExpr parent;
- protected List<SubExpr> children;
- internal SubExpr(SubExpr parent, Opcode ops, int var)
- {
- this.children = new List<SubExpr>(2);
- this.var = var;
- this.parent = parent;
- this.useSpecial = false;
- if (parent != null)
- {
- this.ops = new InternalSubExprOpcode(parent);
- this.ops.Attach(ops);
- this.useSpecial = parent is SubExprHeader && ((SelectOpcode)ops).Criteria.Axis.Type == QueryAxisType.Child;
- }
- else
- {
- this.ops = ops;
- }
- }
- internal Opcode FirstOp
- {
- get
- {
- if (this.parent == null)
- {
- return this.ops;
- }
- else
- {
- return this.ops.Next;
- }
- }
- }
- internal int Variable
- {
- get
- {
- return this.var;
- }
- }
- internal SubExprOpcode Add(Opcode opseq, SubExprEliminator elim)
- {
- Opcode start = this.FirstOp;
- Opcode ops = opseq;
- while (start != null && ops != null && start.Equals(ops))
- {
- start = start.Next;
- ops = ops.Next;
- }
- if (ops == null)
- {
- if (start == null)
- {
- return new SubExprOpcode(this);
- }
- else
- {
- SubExpr e = this.BranchAt(start, elim);
- return new SubExprOpcode(e);
- }
- }
- else
- {
- if (start == null)
- {
- ops.DetachFromParent();
- for (int i = 0; i < this.children.Count; ++i)
- {
- if (this.children[i].FirstOp.Equals(ops))
- {
- return this.children[i].Add(ops, elim);
- }
- }
- SubExpr e = new SubExpr(this, ops, elim.NewVarID());
- this.AddChild(e);
- return new SubExprOpcode(e);
- }
- else
- {
- SubExpr e = this.BranchAt(start, elim);
- ops.DetachFromParent();
- SubExpr ee = new SubExpr(e, ops, elim.NewVarID());
- e.AddChild(ee);
- return new SubExprOpcode(ee);
- }
- }
- }
- internal virtual void AddChild(SubExpr expr)
- {
- this.children.Add(expr);
- }
- SubExpr BranchAt(Opcode op, SubExprEliminator elim)
- {
- Opcode firstOp = this.FirstOp;
- if (this.parent != null)
- {
- this.parent.RemoveChild(this);
- }
- else
- {
- elim.Exprs.Remove(this);
- }
- firstOp.DetachFromParent();
- op.DetachFromParent();
- SubExpr e = new SubExpr(this.parent, firstOp, elim.NewVarID());
- if (this.parent != null)
- {
- this.parent.AddChild(e);
- }
- else
- {
- elim.Exprs.Add(e);
- }
- e.AddChild(this);
- this.parent = e;
- this.ops = new InternalSubExprOpcode(e);
- this.ops.Attach(op);
- return e;
- }
- internal void CleanUp(SubExprEliminator elim)
- {
- if (this.refCount == 0)
- {
- if (this.children.Count == 0)
- {
- if (this.parent == null)
- {
- elim.Exprs.Remove(this);
- }
- else
- {
- this.parent.RemoveChild(this);
- this.parent.CleanUp(elim);
- }
- }
- else if (this.children.Count == 1)
- {
- SubExpr child = this.children[0];
- Opcode op = child.FirstOp;
- op.DetachFromParent();
- Opcode op2 = this.ops;
- while (op2.Next != null)
- {
- op2 = op2.Next;
- }
- op2.Attach(op);
- child.ops = this.ops;
- if (this.parent == null)
- {
- elim.Exprs.Remove(this);
- elim.Exprs.Add(child);
- child.parent = null;
- }
- else
- {
- this.parent.RemoveChild(this);
- this.parent.AddChild(child);
- child.parent = this.parent;
- }
- }
- }
- }
- internal void DecRef(SubExprEliminator elim)
- {
- this.refCount--;
- CleanUp(elim);
- }
- internal void Eval(ProcessingContext context)
- {
- int count = 0, marker = context.Processor.CounterMarker;
- Opcode op = this.ops;
- if (this.useSpecial)
- {
- op.EvalSpecial(context);
- context.LoadVariable(this.var);
- //context.Processor.CounterMarker = marker;
- return;
- }
- while (op != null)
- {
- op = op.Eval(context);
- }
- count = context.Processor.ElapsedCount(marker);
- //context.Processor.CounterMarker = marker;
- context.SaveVariable(this.var, count);
- }
- internal virtual void EvalSpecial(ProcessingContext context)
- {
- this.Eval(context);
- }
- internal void IncRef()
- {
- this.refCount++;
- }
- internal virtual void RemoveChild(SubExpr expr)
- {
- this.children.Remove(expr);
- }
- internal void Renumber(SubExprEliminator elim)
- {
- this.var = elim.NewVarID();
- for (int i = 0; i < this.children.Count; ++i)
- {
- this.children[i].Renumber(elim);
- }
- }
- internal void Trim()
- {
- this.children.Capacity = this.children.Count;
- this.ops.Trim();
- for (int i = 0; i < this.children.Count; ++i)
- {
- this.children[i].Trim();
- }
- }
- #if DEBUG_FILTER
- internal void Write(TextWriter outStream)
- {
- outStream.WriteLine("=======================");
- outStream.WriteLine("= SubExpr #" + this.var.ToString() + " (" + this.refCount.ToString() + ")");
- outStream.WriteLine("=======================");
- for(Opcode o = this.ops; o != null; o = o.Next)
- {
- outStream.WriteLine(o.ToString());
- }
- outStream.WriteLine("");
- for(int i = 0; i < this.children.Count; ++i)
- {
- this.children[i].Write(outStream);
- }
- }
- #endif
- }
- internal class SubExprHeader : SubExpr
- {
- // WS, [....], Can probably combine these
- // WS, [....], Make this data structure less ugly (if possible)
- Dictionary<string, Dictionary<string, List<SubExpr>>> nameLookup;
- Dictionary<SubExpr, MyInt> indexLookup;
- internal SubExprHeader(Opcode ops, int var)
- : base(null, ops, var)
- {
- this.nameLookup = new Dictionary<string, Dictionary<string, List<SubExpr>>>();
- this.indexLookup = new Dictionary<SubExpr, MyInt>();
- this.IncRef(); // Prevent cleanup
- }
- internal override void AddChild(SubExpr expr)
- {
- base.AddChild(expr);
- RebuildIndex();
- if (expr.useSpecial)
- {
- NodeQName qname = ((SelectOpcode)(expr.FirstOp)).Criteria.QName;
- string ns = qname.Namespace;
- Dictionary<string, List<SubExpr>> nextLookup;
- if (!this.nameLookup.TryGetValue(ns, out nextLookup))
- {
- nextLookup = new Dictionary<string, List<SubExpr>>();
- this.nameLookup.Add(ns, nextLookup);
- }
- string name = qname.Name;
- List<SubExpr> exprs = new List<SubExpr>();
- if (!nextLookup.TryGetValue(name, out exprs))
- {
- exprs = new List<SubExpr>();
- nextLookup.Add(name, exprs);
- }
- exprs.Add(expr);
- }
- }
- internal override void EvalSpecial(ProcessingContext context)
- {
- int marker = context.Processor.CounterMarker;
- if (!context.LoadVariable(this.var))
- {
- XPathMessageContext.HeaderFun.InvokeInternal(context, 0);
- context.SaveVariable(this.var, context.Processor.ElapsedCount(marker));
- }
- // WS, [....], see if we can put this array in the processor to save
- // an allocation. Perhaps we can use the variables slot we're going to fill
- NodeSequence[] childSequences = new NodeSequence[this.children.Count];
- NodeSequence seq = context.Sequences[context.TopSequenceArg.basePtr].Sequence;
- for (int i = 0; i < this.children.Count; ++i)
- {
- childSequences[i] = context.CreateSequence();
- childSequences[i].StartNodeset();
- }
- // Perform the index
- SeekableXPathNavigator nav = seq[0].GetNavigator();
- if (nav.MoveToFirstChild())
- {
- do
- {
- if (nav.NodeType == XPathNodeType.Element)
- {
- List<SubExpr> lst;
- string name = nav.LocalName;
- string ns = nav.NamespaceURI;
- Dictionary<string, List<SubExpr>> nextLookup;
- if (this.nameLookup.TryGetValue(ns, out nextLookup))
- {
- if (nextLookup.TryGetValue(name, out lst))
- {
- for (int i = 0; i < lst.Count; ++i)
- {
- childSequences[this.indexLookup[lst[i]].i].Add(nav);
- }
- }
- if (nextLookup.TryGetValue(QueryDataModel.Wildcard, out lst))
- {
- for (int i = 0; i < lst.Count; ++i)
- {
- childSequences[this.indexLookup[lst[i]].i].Add(nav);
- }
- }
- }
- if (this.nameLookup.TryGetValue(QueryDataModel.Wildcard, out nextLookup))
- {
- if (nextLookup.TryGetValue(QueryDataModel.Wildcard, out lst))
- {
- for (int i = 0; i < lst.Count; ++i)
- {
- childSequences[this.indexLookup[lst[i]].i].Add(nav);
- }
- }
- }
- }
- } while (nav.MoveToNext());
- }
- int secondMarker = context.Processor.CounterMarker;
- for (int i = 0; i < this.children.Count; ++i)
- {
- if (this.children[i].useSpecial)
- {
- childSequences[i].StopNodeset();
- context.Processor.CounterMarker = secondMarker;
- context.PushSequenceFrame();
- context.PushSequence(childSequences[i]);
- Opcode op = this.children[i].FirstOp.Next;
- while (op != null)
- {
- op = op.Eval(context);
- }
- context.SaveVariable(this.children[i].var, context.Processor.ElapsedCount(marker));
- context.PopSequenceFrame();
- }
- else
- {
- context.ReleaseSequence(childSequences[i]);
- //context.SetVariable(this.children[i].Variable, null, 0);
- }
- }
- context.Processor.CounterMarker = marker;
- }
- internal void RebuildIndex()
- {
- this.indexLookup.Clear();
- for (int i = 0; i < this.children.Count; ++i)
- {
- this.indexLookup.Add(this.children[i], new MyInt(i));
- }
- }
- internal override void RemoveChild(SubExpr expr)
- {
- base.RemoveChild(expr);
- RebuildIndex();
- if (expr.useSpecial)
- {
- NodeQName qname = ((SelectOpcode)(expr.FirstOp)).Criteria.QName;
- string ns = qname.Namespace;
- Dictionary<string, List<SubExpr>> nextLookup;
- if (this.nameLookup.TryGetValue(ns, out nextLookup))
- {
- string name = qname.Name;
- List<SubExpr> exprs;
- if (nextLookup.TryGetValue(name, out exprs))
- {
- exprs.Remove(expr);
- if (exprs.Count == 0)
- {
- nextLookup.Remove(name);
- }
- }
- if (nextLookup.Count == 0)
- {
- this.nameLookup.Remove(ns);
- }
- }
- }
- }
- internal class MyInt
- {
- internal int i;
- internal MyInt(int i)
- {
- this.i = i;
- }
- }
- }
- internal class SubExprEliminator
- {
- List<SubExpr> exprList;
- int nextVar;
- Dictionary<object, List<SubExpr>> removalMapping;
- internal SubExprEliminator()
- {
- this.removalMapping = new Dictionary<object, List<SubExpr>>();
- this.exprList = new List<SubExpr>();
- Opcode op = new XPathMessageFunctionCallOpcode(XPathMessageContext.HeaderFun, 0);
- SubExprHeader header = new SubExprHeader(op, 0);
- this.exprList.Add(header);
- this.nextVar = 1;
- }
- internal List<SubExpr> Exprs
- {
- get
- {
- return this.exprList;
- }
- }
- internal int VariableCount
- {
- get
- {
- return this.nextVar;
- }
- }
- internal Opcode Add(object item, Opcode ops)
- {
- List<SubExpr> exprs = new List<SubExpr>();
- this.removalMapping.Add(item, exprs);
- while (ops.Next != null)
- {
- ops = ops.Next;
- }
- Opcode res = ops;
- while (ops != null)
- {
- if (IsExprStarter(ops))
- {
- Opcode start = ops;
- Opcode p = ops.Prev;
- ops.DetachFromParent();
- ops = ops.Next;
- while (ops.ID == OpcodeID.Select)
- {
- ops = ops.Next;
- }
- ops.DetachFromParent();
- SubExpr e = null;
- for (int i = 0; i < this.exprList.Count; ++i)
- {
- if (this.exprList[i].FirstOp.Equals(start))
- {
- e = this.exprList[i];
- break;
- }
- }
- SubExprOpcode o;
- if (e == null)
- {
- e = new SubExpr(null, start, NewVarID());
- this.exprList.Add(e);
- o = new SubExprOpcode(e);
- }
- else
- {
- o = e.Add(start, this);
- }
- o.Expr.IncRef();
- exprs.Add(o.Expr);
- o.Attach(ops);
- ops = o;
- if (p != null)
- {
- p.Attach(ops);
- }
- }
- res = ops;
- ops = ops.Prev;
- }
- return res;
- }
- internal static bool IsExprStarter(Opcode op)
- {
- if (op.ID == OpcodeID.SelectRoot)
- {
- return true;
- }
- if (op.ID == OpcodeID.XsltInternalFunction)
- {
- XPathMessageFunctionCallOpcode fop = (XPathMessageFunctionCallOpcode)op;
- if (fop.ReturnType == XPathResultType.NodeSet && fop.ArgCount == 0)
- {
- return true;
- }
- }
- return false;
- }
- internal int NewVarID()
- {
- return nextVar++;
- }
- internal void Remove(object item)
- {
- List<SubExpr> exprs;
- if (this.removalMapping.TryGetValue(item, out exprs))
- {
- for (int i = 0; i < exprs.Count; ++i)
- {
- exprs[i].DecRef(this);
- }
- this.removalMapping.Remove(item);
- Renumber();
- }
- }
- void Renumber()
- {
- this.nextVar = 0;
- for (int i = 0; i < this.exprList.Count; ++i)
- {
- this.exprList[i].Renumber(this);
- }
- }
- internal void Trim()
- {
- this.exprList.Capacity = this.exprList.Count;
- for (int i = 0; i < this.exprList.Count; ++i)
- {
- this.exprList[i].Trim();
- }
- }
- #if DEBUG_FILTER
- internal void Write(TextWriter outStream)
- {
- for(int i = 0; i < this.exprList.Count; ++i)
- {
- this.exprList[i].Write(outStream);
- }
- }
- #endif
- }
- internal class SubExprOpcode : Opcode
- {
- protected SubExpr expr;
- internal SubExprOpcode(SubExpr expr)
- : base(OpcodeID.SubExpr)
- {
- this.expr = expr;
- }
- internal SubExpr Expr
- {
- get
- {
- return expr;
- }
- }
- internal override bool Equals(Opcode op)
- {
- if (base.Equals(op))
- {
- SubExprOpcode sop = op as SubExprOpcode;
- if (sop != null)
- {
- return this.expr == sop.expr;
- }
- }
- return false;
- }
- internal override Opcode Eval(ProcessingContext context)
- {
- if (!context.LoadVariable(this.expr.Variable))
- {
- context.PushSequenceFrame();
- NodeSequence seq = context.CreateSequence();
- seq.Add(context.Processor.ContextNode);
- context.PushSequence(seq);
- int marker = context.Processor.CounterMarker;
- try
- {
- this.expr.Eval(context);
- }
- catch (XPathNavigatorException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e.Process(this));
- }
- catch (NavigatorInvalidBodyAccessException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e.Process(this));
- }
- context.Processor.CounterMarker = marker;
- context.PopSequenceFrame();
- context.PopSequenceFrame();
- context.LoadVariable(this.expr.Variable);
- }
- return this.next;
- }
- internal override Opcode EvalSpecial(ProcessingContext context)
- {
- try
- {
- this.expr.EvalSpecial(context);
- }
- catch (XPathNavigatorException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e.Process(this));
- }
- catch (NavigatorInvalidBodyAccessException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e.Process(this));
- }
- return this.next;
- }
- #if DEBUG_FILTER
- public override string ToString()
- {
- return string.Format("{0} #{1}", base.ToString(), this.expr.Variable.ToString());
- }
- #endif
- }
- internal class InternalSubExprOpcode : SubExprOpcode
- {
- internal InternalSubExprOpcode(SubExpr expr)
- : base(expr)
- {
- }
- internal override Opcode Eval(ProcessingContext context)
- {
- if (!context.LoadVariable(this.expr.Variable))
- {
- this.expr.Eval(context);
- }
- return this.next;
- }
- internal override Opcode EvalSpecial(ProcessingContext context)
- {
- this.expr.EvalSpecial(context);
- return this.next;
- }
- }
- }
|