Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / XmlUtils / System / Xml / Xsl / XmlIlGenerator.cs / 1 / XmlIlGenerator.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //----------------------------------------------------------------------------- using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Security; using System.Xml.XPath; using System.Xml.Xsl.IlGen; using System.Xml.Xsl.Qil; using System.Xml.Xsl.Runtime; namespace System.Xml.Xsl { internal delegate void ExecuteDelegate(XmlQueryRuntime runtime); ////// This internal class is the entry point for creating Msil assemblies from QilExpression. /// ////// Generate will return an AssemblyBuilder with the following setup: /// Assembly Name = "MS.Internal.Xml.CompiledQuery" /// Module Dll Name = "MS.Internal.Xml.CompiledQuery.dll" /// public class MS.Internal.Xml.CompiledQuery.Test { /// public static void Execute(XmlQueryRuntime runtime); /// public static void Root(XmlQueryRuntime runtime); /// private static ... UserMethod1(XmlQueryRuntime runtime, ...); /// ... /// private static ... UserMethodN(XmlQueryRuntime runtime, ...); /// } /// /// XmlILGenerator incorporates a number of different technologies in order to generate efficient code that avoids caching /// large result sets in memory: /// /// 1. Code Iterators - Query results are computed using a set of composable, interlocking iterators that alone perform a /// simple task, but together execute complex queries. The iterators are actually little blocks of code /// that are connected to each other using a series of jumps. Because each iterator is not instantiated /// as a separate object, the number of objects and number of function calls is kept to a minimum during /// execution. Also, large result sets are often computed incrementally, with each iterator performing one step in a /// pipeline of sequence items. /// /// 2. Analyzers - During code generation, QilToMsil traverses the semantic tree representation of the query (QIL) several times. /// As visits to each node in the tree start and end, various Analyzers are invoked. These Analyzers incrementally /// collect and store information that is later used to generate faster and smaller code. /// internal class XmlILGenerator { private QilExpression qil; private GenerateHelper helper; private XmlILOptimizerVisitor optVisitor; private XmlILVisitor xmlIlVisitor; private XmlILModule module; ////// Always output debug information in debug mode. /// public XmlILGenerator() { } ////// Given the logical query plan (QilExpression) generate a physical query plan (MSIL) that can be executed. /// public XmlILCommand Generate(QilExpression query, TypeBuilder typeBldr) { MethodInfo methRoot, methExec; bool useLRE, emitSymbols; XmlQueryStaticData staticData; ExecuteDelegate delExec; XmlILMethodAttributes methAttrs; this.qil = query; useLRE = !this.qil.IsDebug && (typeBldr == null); emitSymbols = this.qil.IsDebug; // In debug code, ensure that input QIL is correct QilValidationVisitor.Validate(this.qil); // Trace Qil before optimization XmlILTrace.WriteQil(this.qil, "qilbefore.xml"); // Trace optimizations XmlILTrace.TraceOptimizations(this.qil, "qilopt.xml"); if (XmlILTrace.IsEnabled) { // Dump assembly to disk; can't do this when using LRE useLRE = false; } // Optimize and annotate the Qil graph this.optVisitor = new XmlILOptimizerVisitor(this.qil, !this.qil.IsDebug); this.qil = this.optVisitor.Optimize(); // In debug code, ensure that output QIL is correct QilValidationVisitor.Validate(this.qil); // Trace Qil after optimization XmlILTrace.WriteQil(this.qil, "qilafter.xml"); try { XmlILModule.CreateModulePermissionSet.Assert(); // Create module in which methods will be generated if (typeBldr != null) this.module = new XmlILModule(typeBldr); else this.module = new XmlILModule(useLRE, emitSymbols); // Create a code generation helper for the module; enable optimizations if IsDebug is false this.helper = new GenerateHelper(this.module, this.qil.IsDebug); // Create helper methods CreateHelperFunctions(); // Create metadata for the Execute function, which is the entry point to the query // public static void Execute(XmlQueryRuntime); methExec = this.module.DefineMethod("Execute", typeof(void), new Type[] {}, new string[] {}, XmlILMethodAttributes.NonUser); // Create metadata for the root expression // public void Root() Debug.Assert(this.qil.Root != null); methAttrs = (this.qil.Root.SourceLine == null) ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None; methRoot = this.module.DefineMethod("Root", typeof(void), new Type[] {}, new string[] {}, methAttrs); // Declare all early bound function objects foreach (EarlyBoundInfo info in this.qil.EarlyBoundTypes) this.helper.StaticData.DeclareEarlyBound(info.NamespaceUri, info.EarlyBoundType); // Create metadata for each QilExpression function that has at least one caller CreateFunctionMetadata(this.qil.FunctionList); // Create metadata for each QilExpression global variable and parameter CreateGlobalValueMetadata(this.qil.GlobalVariableList); CreateGlobalValueMetadata(this.qil.GlobalParameterList); // Generate Execute method GenerateExecuteFunction(methExec, methRoot); // Visit the QilExpression graph this.xmlIlVisitor = new XmlILVisitor(); this.xmlIlVisitor.Visit(this.qil, this.helper, methRoot); // Collect all static information required by the runtime staticData = new XmlQueryStaticData( this.qil.DefaultWriterSettings, this.qil.WhitespaceRules, this.helper.StaticData); // Create static constructor that initializes XmlQueryStaticData instance at runtime if (typeBldr != null) CreateTypeInitializer(staticData); // Finish up creation of the type this.module.BakeMethods(); // Create delegate over "Execute" method delExec = (ExecuteDelegate) this.module.CreateDelegate("Execute", typeof(ExecuteDelegate)); return new XmlILCommand(delExec, staticData); } finally { CodeAccessPermission.RevertAssert(); } } ////// Create MethodBuilder metadata for the specified QilExpression function. Annotate ndFunc with the /// MethodBuilder. Also, each QilExpression argument type should be converted to a corresponding Clr type. /// Each argument QilExpression node should be annotated with the resulting ParameterBuilder. /// private void CreateFunctionMetadata(IListfuncList) { MethodInfo methInfo; Type[] paramTypes; string[] paramNames; Type typReturn; XmlILMethodAttributes methAttrs; foreach (QilFunction ndFunc in funcList) { paramTypes = new Type[ndFunc.Arguments.Count]; paramNames = new string[ndFunc.Arguments.Count]; // Loop through all other parameters and save their types in the array for (int arg = 0; arg < ndFunc.Arguments.Count; arg ++) { QilParameter ndParam = (QilParameter) ndFunc.Arguments[arg]; Debug.Assert(ndParam.NodeType == QilNodeType.Parameter); // Get the type of each argument as a Clr type paramTypes[arg] = XmlILTypeHelper.GetStorageType(ndParam.XmlType); // Get the name of each argument if (ndParam.DebugName != null) paramNames[arg] = ndParam.DebugName; } // Get the type of the return value if (XmlILConstructInfo.Read(ndFunc).PushToWriterLast) { // Push mode functions do not have a return value typReturn = typeof(void); } else { // Pull mode functions have a return value typReturn = XmlILTypeHelper.GetStorageType(ndFunc.XmlType); } // Create the method metadata methAttrs = ndFunc.SourceLine == null ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None; methInfo = this.module.DefineMethod(ndFunc.DebugName, typReturn, paramTypes, paramNames, methAttrs); for (int arg = 0; arg < ndFunc.Arguments.Count; arg ++) { // Set location of parameter on Let node annotation XmlILAnnotation.Write(ndFunc.Arguments[arg]).ArgumentPosition = arg; } // Annotate function with the MethodInfo XmlILAnnotation.Write(ndFunc).FunctionBinding = methInfo; } } /// /// Generate metadata for a method that calculates a global value. /// private void CreateGlobalValueMetadata(IListglobalList) { MethodInfo methInfo; Type typReturn; XmlILMethodAttributes methAttrs; foreach (QilReference ndRef in globalList) { // public T GlobalValue() typReturn = XmlILTypeHelper.GetStorageType(ndRef.XmlType); methAttrs = ndRef.SourceLine == null ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None; methInfo = this.module.DefineMethod(ndRef.DebugName.ToString(), typReturn, new Type[] {}, new string[] {}, methAttrs); // Annotate function with MethodBuilder XmlILAnnotation.Write(ndRef).FunctionBinding = methInfo; } } /// /// Generate the "Execute" method, which is the entry point to the query. /// private MethodInfo GenerateExecuteFunction(MethodInfo methExec, MethodInfo methRoot) { this.helper.MethodBegin(methExec, null, false); // Force some or all global values to be evaluated at start of query EvaluateGlobalValues(this.qil.GlobalVariableList); EvaluateGlobalValues(this.qil.GlobalParameterList); // Root(runtime); this.helper.LoadQueryRuntime(); this.helper.Call(methRoot); this.helper.MethodEnd(); return methExec; } ////// Create and generate various helper methods, which are called by the generated code. /// private void CreateHelperFunctions() { MethodInfo meth; Label lblClone; // public static XPathNavigator SyncToNavigator(XPathNavigator, XPathNavigator); meth = this.module.DefineMethod( "SyncToNavigator", typeof(XPathNavigator), new Type[] {typeof(XPathNavigator), typeof(XPathNavigator)}, new string[] {null, null}, XmlILMethodAttributes.NonUser | XmlILMethodAttributes.Raw); this.helper.MethodBegin(meth, null, false); // if (navigatorThis != null && navigatorThis.MoveTo(navigatorThat)) // return navigatorThis; lblClone = this.helper.DefineLabel(); this.helper.Emit(OpCodes.Ldarg_0); this.helper.Emit(OpCodes.Brfalse, lblClone); this.helper.Emit(OpCodes.Ldarg_0); this.helper.Emit(OpCodes.Ldarg_1); this.helper.Call(XmlILMethods.NavMoveTo); this.helper.Emit(OpCodes.Brfalse, lblClone); this.helper.Emit(OpCodes.Ldarg_0); this.helper.Emit(OpCodes.Ret); // LabelClone: // return navigatorThat.Clone(); this.helper.MarkLabel(lblClone); this.helper.Emit(OpCodes.Ldarg_1); this.helper.Call(XmlILMethods.NavClone); this.helper.MethodEnd(); } ////// Generate code to force evaluation of some or all global variables and/or parameters. /// private void EvaluateGlobalValues(IListiterList) { MethodInfo methInfo; foreach (QilIterator ndIter in iterList) { // Evaluate global if generating debug code, or if global might have side effects if (this.qil.IsDebug || OptimizerPatterns.Read(ndIter).MatchesPattern(OptimizerPatternName.MaybeSideEffects)) { // Get MethodInfo that evaluates the global value and discard its return value methInfo = XmlILAnnotation.Write(ndIter).FunctionBinding; Debug.Assert(methInfo != null, "MethodInfo for global value should have been created previously."); this.helper.LoadQueryRuntime(); this.helper.Call(methInfo); this.helper.Emit(OpCodes.Pop); } } } /// /// Create static constructor that initializes XmlQueryStaticData instance at runtime. /// public void CreateTypeInitializer(XmlQueryStaticData staticData) { byte[] data; Type[] ebTypes; FieldInfo fldInitData, fldData, fldTypes; ConstructorInfo cctor; staticData.GetObjectData(out data, out ebTypes); fldInitData = this.module.DefineInitializedData("__" + XmlQueryStaticData.DataFieldName, data); fldData = this.module.DefineField(XmlQueryStaticData.DataFieldName, typeof(object)); fldTypes = this.module.DefineField(XmlQueryStaticData.TypesFieldName, typeof(Type[])); cctor = this.module.DefineTypeInitializer(); this.helper.MethodBegin(cctor, null, false); // s_data = new byte[s_initData.Length] { s_initData }; this.helper.LoadInteger(data.Length); this.helper.Emit(OpCodes.Newarr, typeof(byte)); this.helper.Emit(OpCodes.Dup); this.helper.Emit(OpCodes.Ldtoken, fldInitData); this.helper.Call(XmlILMethods.InitializeArray); this.helper.Emit(OpCodes.Stsfld, fldData); if (ebTypes != null) { // Type[] types = new Type[s_ebTypes.Length]; LocalBuilder locTypes = this.helper.DeclareLocal("$$$types", typeof(Type[])); this.helper.LoadInteger(ebTypes.Length); this.helper.Emit(OpCodes.Newarr, typeof(Type)); this.helper.Emit(OpCodes.Stloc, locTypes); for (int idx = 0; idx < ebTypes.Length; idx++) { // types[idx] = ebTypes[idx]; this.helper.Emit(OpCodes.Ldloc, locTypes); this.helper.LoadInteger(idx); this.helper.LoadType(ebTypes[idx]); this.helper.Emit(OpCodes.Stelem_Ref); } // s_types = types; this.helper.Emit(OpCodes.Ldloc, locTypes); this.helper.Emit(OpCodes.Stsfld, fldTypes); } this.helper.MethodEnd(); } } ////// This is the executable command generated by the XmlILGenerator. /// internal class XmlILCommand : XmlCommand { private ExecuteDelegate delExec; private XmlQueryStaticData staticData; ////// Constructor. /// public XmlILCommand(ExecuteDelegate delExec, XmlQueryStaticData staticData) { Debug.Assert(delExec != null && staticData != null); this.delExec = delExec; this.staticData = staticData; } ////// Return execute delegate. /// public ExecuteDelegate ExecuteDelegate { get { return delExec; } } ////// Return query static data required by the runtime. /// public XmlQueryStaticData StaticData { get { return staticData; } } ////// Default document as XPathNavigator. /// public override void Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results) { if (results == null) throw new ArgumentNullException("results"); if (contextDocument != null) Execute(contextDocument.CreateNavigator(), dataSources, argumentList, results, false); else Execute(null, dataSources, argumentList, results, false); } ////// Default document as XPathNavigator. /// public override void Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, TextWriter results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, XmlWriter.Create(results, this.staticData.DefaultWriterSettings)); } ////// Default document as XPathNavigator. /// public override void Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, Stream results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, XmlWriter.Create(results, this.staticData.DefaultWriterSettings)); } ////// Executes the query by accessing datasources via the XmlResolver and using run-time parameters /// as provided by the XsltArgumentList. The default document is mapped into the XmlResolver with the /// provided name. The results are output to the provided XmlWriter. /// public void Execute(string contextDocumentUri, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocumentUri, dataSources, argumentList, results, false); } ////// Executes the query by accessing datasources via the XmlResolver and using /// run-time parameters as provided by the XsltArgumentList. The default document /// is mapped into the XmlResolver with the provided name. The results are returned /// as an IList. /// public IList Evaluate(string contextDocumentUri, XmlResolver dataSources, XsltArgumentList argumentList) { XmlCachedSequenceWriter seqwrt = new XmlCachedSequenceWriter(); Execute(contextDocumentUri, dataSources, argumentList, seqwrt); return seqwrt.ResultSequence; } ////// Executes the query by accessing datasources via the XmlResolver and using run-time parameters /// as provided by the XsltArgumentList. The default document is mapped into the XmlResolver with the /// provided name. The results are output to the provided XmlWriter. /// public override void Execute(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, results, false); } ////// Executes the query by accessing datasources via the XmlResolver and using run-time parameters /// as provided by the XsltArgumentList. The default document is mapped into the XmlResolver with the /// provided name. The results are output to the provided TextWriter. /// public override void Execute(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, TextWriter results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, XmlWriter.Create(results, this.staticData.DefaultWriterSettings), true); } ////// Executes the query by accessing datasources via the XmlResolver and using run-time parameters /// as provided by the XsltArgumentList. The default document is mapped into the XmlResolver with the /// provided name. The results are output to the provided Stream. /// public override void Execute(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, Stream results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, XmlWriter.Create(results, this.staticData.DefaultWriterSettings), true); } ////// Executes the query by accessing datasources via the XmlResolver and using /// run-time parameters as provided by the XsltArgumentList. The default document /// is mapped into the XmlResolver with the provided name. The results are returned /// as an IList. /// public override IList Evaluate(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList) { XmlCachedSequenceWriter seqwrt = new XmlCachedSequenceWriter(); Execute(contextDocument, dataSources, argumentList, seqwrt); return seqwrt.ResultSequence; } ////// Execute the dynamic assembly generated by the XmlILGenerator. /// private void Execute(object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, bool closeWriter) { try { // Try to extract a RawWriter XmlWellFormedWriter wellFormedWriter = writer as XmlWellFormedWriter; if (wellFormedWriter != null && wellFormedWriter.WriteState == WriteState.Start && wellFormedWriter.Settings.ConformanceLevel != ConformanceLevel.Document) { // Extracted RawWriter from WellFormedWriter Execute(defaultDocument, dataSources, argumentList, new XmlMergeSequenceWriter(wellFormedWriter.RawWriter)); } else { // Wrap Writer in RawWriter Execute(defaultDocument, dataSources, argumentList, new XmlMergeSequenceWriter(new XmlRawWriterWrapper(writer))); } } finally { // Close Writers that are created by XmlILGenerator; flush external writers if (closeWriter) writer.Close(); else writer.Flush(); } } ////// Execute the dynamic assembly generated by the XmlILGenerator. /// private void Execute(object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results) { Debug.Assert(results != null); // Ensure that dataSources is always non-null if (dataSources == null) dataSources = XmlNullResolver.Singleton; this.delExec(new XmlQueryRuntime(this.staticData, defaultDocument, dataSources, argumentList, results)); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //[....] //[....] //----------------------------------------------------------------------------- using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Security; using System.Xml.XPath; using System.Xml.Xsl.IlGen; using System.Xml.Xsl.Qil; using System.Xml.Xsl.Runtime; namespace System.Xml.Xsl { internal delegate void ExecuteDelegate(XmlQueryRuntime runtime); ////// This internal class is the entry point for creating Msil assemblies from QilExpression. /// ////// Generate will return an AssemblyBuilder with the following setup: /// Assembly Name = "MS.Internal.Xml.CompiledQuery" /// Module Dll Name = "MS.Internal.Xml.CompiledQuery.dll" /// public class MS.Internal.Xml.CompiledQuery.Test { /// public static void Execute(XmlQueryRuntime runtime); /// public static void Root(XmlQueryRuntime runtime); /// private static ... UserMethod1(XmlQueryRuntime runtime, ...); /// ... /// private static ... UserMethodN(XmlQueryRuntime runtime, ...); /// } /// /// XmlILGenerator incorporates a number of different technologies in order to generate efficient code that avoids caching /// large result sets in memory: /// /// 1. Code Iterators - Query results are computed using a set of composable, interlocking iterators that alone perform a /// simple task, but together execute complex queries. The iterators are actually little blocks of code /// that are connected to each other using a series of jumps. Because each iterator is not instantiated /// as a separate object, the number of objects and number of function calls is kept to a minimum during /// execution. Also, large result sets are often computed incrementally, with each iterator performing one step in a /// pipeline of sequence items. /// /// 2. Analyzers - During code generation, QilToMsil traverses the semantic tree representation of the query (QIL) several times. /// As visits to each node in the tree start and end, various Analyzers are invoked. These Analyzers incrementally /// collect and store information that is later used to generate faster and smaller code. /// internal class XmlILGenerator { private QilExpression qil; private GenerateHelper helper; private XmlILOptimizerVisitor optVisitor; private XmlILVisitor xmlIlVisitor; private XmlILModule module; ////// Always output debug information in debug mode. /// public XmlILGenerator() { } ////// Given the logical query plan (QilExpression) generate a physical query plan (MSIL) that can be executed. /// public XmlILCommand Generate(QilExpression query, TypeBuilder typeBldr) { MethodInfo methRoot, methExec; bool useLRE, emitSymbols; XmlQueryStaticData staticData; ExecuteDelegate delExec; XmlILMethodAttributes methAttrs; this.qil = query; useLRE = !this.qil.IsDebug && (typeBldr == null); emitSymbols = this.qil.IsDebug; // In debug code, ensure that input QIL is correct QilValidationVisitor.Validate(this.qil); // Trace Qil before optimization XmlILTrace.WriteQil(this.qil, "qilbefore.xml"); // Trace optimizations XmlILTrace.TraceOptimizations(this.qil, "qilopt.xml"); if (XmlILTrace.IsEnabled) { // Dump assembly to disk; can't do this when using LRE useLRE = false; } // Optimize and annotate the Qil graph this.optVisitor = new XmlILOptimizerVisitor(this.qil, !this.qil.IsDebug); this.qil = this.optVisitor.Optimize(); // In debug code, ensure that output QIL is correct QilValidationVisitor.Validate(this.qil); // Trace Qil after optimization XmlILTrace.WriteQil(this.qil, "qilafter.xml"); try { XmlILModule.CreateModulePermissionSet.Assert(); // Create module in which methods will be generated if (typeBldr != null) this.module = new XmlILModule(typeBldr); else this.module = new XmlILModule(useLRE, emitSymbols); // Create a code generation helper for the module; enable optimizations if IsDebug is false this.helper = new GenerateHelper(this.module, this.qil.IsDebug); // Create helper methods CreateHelperFunctions(); // Create metadata for the Execute function, which is the entry point to the query // public static void Execute(XmlQueryRuntime); methExec = this.module.DefineMethod("Execute", typeof(void), new Type[] {}, new string[] {}, XmlILMethodAttributes.NonUser); // Create metadata for the root expression // public void Root() Debug.Assert(this.qil.Root != null); methAttrs = (this.qil.Root.SourceLine == null) ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None; methRoot = this.module.DefineMethod("Root", typeof(void), new Type[] {}, new string[] {}, methAttrs); // Declare all early bound function objects foreach (EarlyBoundInfo info in this.qil.EarlyBoundTypes) this.helper.StaticData.DeclareEarlyBound(info.NamespaceUri, info.EarlyBoundType); // Create metadata for each QilExpression function that has at least one caller CreateFunctionMetadata(this.qil.FunctionList); // Create metadata for each QilExpression global variable and parameter CreateGlobalValueMetadata(this.qil.GlobalVariableList); CreateGlobalValueMetadata(this.qil.GlobalParameterList); // Generate Execute method GenerateExecuteFunction(methExec, methRoot); // Visit the QilExpression graph this.xmlIlVisitor = new XmlILVisitor(); this.xmlIlVisitor.Visit(this.qil, this.helper, methRoot); // Collect all static information required by the runtime staticData = new XmlQueryStaticData( this.qil.DefaultWriterSettings, this.qil.WhitespaceRules, this.helper.StaticData); // Create static constructor that initializes XmlQueryStaticData instance at runtime if (typeBldr != null) CreateTypeInitializer(staticData); // Finish up creation of the type this.module.BakeMethods(); // Create delegate over "Execute" method delExec = (ExecuteDelegate) this.module.CreateDelegate("Execute", typeof(ExecuteDelegate)); return new XmlILCommand(delExec, staticData); } finally { CodeAccessPermission.RevertAssert(); } } ////// Create MethodBuilder metadata for the specified QilExpression function. Annotate ndFunc with the /// MethodBuilder. Also, each QilExpression argument type should be converted to a corresponding Clr type. /// Each argument QilExpression node should be annotated with the resulting ParameterBuilder. /// private void CreateFunctionMetadata(IListfuncList) { MethodInfo methInfo; Type[] paramTypes; string[] paramNames; Type typReturn; XmlILMethodAttributes methAttrs; foreach (QilFunction ndFunc in funcList) { paramTypes = new Type[ndFunc.Arguments.Count]; paramNames = new string[ndFunc.Arguments.Count]; // Loop through all other parameters and save their types in the array for (int arg = 0; arg < ndFunc.Arguments.Count; arg ++) { QilParameter ndParam = (QilParameter) ndFunc.Arguments[arg]; Debug.Assert(ndParam.NodeType == QilNodeType.Parameter); // Get the type of each argument as a Clr type paramTypes[arg] = XmlILTypeHelper.GetStorageType(ndParam.XmlType); // Get the name of each argument if (ndParam.DebugName != null) paramNames[arg] = ndParam.DebugName; } // Get the type of the return value if (XmlILConstructInfo.Read(ndFunc).PushToWriterLast) { // Push mode functions do not have a return value typReturn = typeof(void); } else { // Pull mode functions have a return value typReturn = XmlILTypeHelper.GetStorageType(ndFunc.XmlType); } // Create the method metadata methAttrs = ndFunc.SourceLine == null ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None; methInfo = this.module.DefineMethod(ndFunc.DebugName, typReturn, paramTypes, paramNames, methAttrs); for (int arg = 0; arg < ndFunc.Arguments.Count; arg ++) { // Set location of parameter on Let node annotation XmlILAnnotation.Write(ndFunc.Arguments[arg]).ArgumentPosition = arg; } // Annotate function with the MethodInfo XmlILAnnotation.Write(ndFunc).FunctionBinding = methInfo; } } /// /// Generate metadata for a method that calculates a global value. /// private void CreateGlobalValueMetadata(IListglobalList) { MethodInfo methInfo; Type typReturn; XmlILMethodAttributes methAttrs; foreach (QilReference ndRef in globalList) { // public T GlobalValue() typReturn = XmlILTypeHelper.GetStorageType(ndRef.XmlType); methAttrs = ndRef.SourceLine == null ? XmlILMethodAttributes.NonUser : XmlILMethodAttributes.None; methInfo = this.module.DefineMethod(ndRef.DebugName.ToString(), typReturn, new Type[] {}, new string[] {}, methAttrs); // Annotate function with MethodBuilder XmlILAnnotation.Write(ndRef).FunctionBinding = methInfo; } } /// /// Generate the "Execute" method, which is the entry point to the query. /// private MethodInfo GenerateExecuteFunction(MethodInfo methExec, MethodInfo methRoot) { this.helper.MethodBegin(methExec, null, false); // Force some or all global values to be evaluated at start of query EvaluateGlobalValues(this.qil.GlobalVariableList); EvaluateGlobalValues(this.qil.GlobalParameterList); // Root(runtime); this.helper.LoadQueryRuntime(); this.helper.Call(methRoot); this.helper.MethodEnd(); return methExec; } ////// Create and generate various helper methods, which are called by the generated code. /// private void CreateHelperFunctions() { MethodInfo meth; Label lblClone; // public static XPathNavigator SyncToNavigator(XPathNavigator, XPathNavigator); meth = this.module.DefineMethod( "SyncToNavigator", typeof(XPathNavigator), new Type[] {typeof(XPathNavigator), typeof(XPathNavigator)}, new string[] {null, null}, XmlILMethodAttributes.NonUser | XmlILMethodAttributes.Raw); this.helper.MethodBegin(meth, null, false); // if (navigatorThis != null && navigatorThis.MoveTo(navigatorThat)) // return navigatorThis; lblClone = this.helper.DefineLabel(); this.helper.Emit(OpCodes.Ldarg_0); this.helper.Emit(OpCodes.Brfalse, lblClone); this.helper.Emit(OpCodes.Ldarg_0); this.helper.Emit(OpCodes.Ldarg_1); this.helper.Call(XmlILMethods.NavMoveTo); this.helper.Emit(OpCodes.Brfalse, lblClone); this.helper.Emit(OpCodes.Ldarg_0); this.helper.Emit(OpCodes.Ret); // LabelClone: // return navigatorThat.Clone(); this.helper.MarkLabel(lblClone); this.helper.Emit(OpCodes.Ldarg_1); this.helper.Call(XmlILMethods.NavClone); this.helper.MethodEnd(); } ////// Generate code to force evaluation of some or all global variables and/or parameters. /// private void EvaluateGlobalValues(IListiterList) { MethodInfo methInfo; foreach (QilIterator ndIter in iterList) { // Evaluate global if generating debug code, or if global might have side effects if (this.qil.IsDebug || OptimizerPatterns.Read(ndIter).MatchesPattern(OptimizerPatternName.MaybeSideEffects)) { // Get MethodInfo that evaluates the global value and discard its return value methInfo = XmlILAnnotation.Write(ndIter).FunctionBinding; Debug.Assert(methInfo != null, "MethodInfo for global value should have been created previously."); this.helper.LoadQueryRuntime(); this.helper.Call(methInfo); this.helper.Emit(OpCodes.Pop); } } } /// /// Create static constructor that initializes XmlQueryStaticData instance at runtime. /// public void CreateTypeInitializer(XmlQueryStaticData staticData) { byte[] data; Type[] ebTypes; FieldInfo fldInitData, fldData, fldTypes; ConstructorInfo cctor; staticData.GetObjectData(out data, out ebTypes); fldInitData = this.module.DefineInitializedData("__" + XmlQueryStaticData.DataFieldName, data); fldData = this.module.DefineField(XmlQueryStaticData.DataFieldName, typeof(object)); fldTypes = this.module.DefineField(XmlQueryStaticData.TypesFieldName, typeof(Type[])); cctor = this.module.DefineTypeInitializer(); this.helper.MethodBegin(cctor, null, false); // s_data = new byte[s_initData.Length] { s_initData }; this.helper.LoadInteger(data.Length); this.helper.Emit(OpCodes.Newarr, typeof(byte)); this.helper.Emit(OpCodes.Dup); this.helper.Emit(OpCodes.Ldtoken, fldInitData); this.helper.Call(XmlILMethods.InitializeArray); this.helper.Emit(OpCodes.Stsfld, fldData); if (ebTypes != null) { // Type[] types = new Type[s_ebTypes.Length]; LocalBuilder locTypes = this.helper.DeclareLocal("$$$types", typeof(Type[])); this.helper.LoadInteger(ebTypes.Length); this.helper.Emit(OpCodes.Newarr, typeof(Type)); this.helper.Emit(OpCodes.Stloc, locTypes); for (int idx = 0; idx < ebTypes.Length; idx++) { // types[idx] = ebTypes[idx]; this.helper.Emit(OpCodes.Ldloc, locTypes); this.helper.LoadInteger(idx); this.helper.LoadType(ebTypes[idx]); this.helper.Emit(OpCodes.Stelem_Ref); } // s_types = types; this.helper.Emit(OpCodes.Ldloc, locTypes); this.helper.Emit(OpCodes.Stsfld, fldTypes); } this.helper.MethodEnd(); } } ////// This is the executable command generated by the XmlILGenerator. /// internal class XmlILCommand : XmlCommand { private ExecuteDelegate delExec; private XmlQueryStaticData staticData; ////// Constructor. /// public XmlILCommand(ExecuteDelegate delExec, XmlQueryStaticData staticData) { Debug.Assert(delExec != null && staticData != null); this.delExec = delExec; this.staticData = staticData; } ////// Return execute delegate. /// public ExecuteDelegate ExecuteDelegate { get { return delExec; } } ////// Return query static data required by the runtime. /// public XmlQueryStaticData StaticData { get { return staticData; } } ////// Default document as XPathNavigator. /// public override void Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results) { if (results == null) throw new ArgumentNullException("results"); if (contextDocument != null) Execute(contextDocument.CreateNavigator(), dataSources, argumentList, results, false); else Execute(null, dataSources, argumentList, results, false); } ////// Default document as XPathNavigator. /// public override void Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, TextWriter results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, XmlWriter.Create(results, this.staticData.DefaultWriterSettings)); } ////// Default document as XPathNavigator. /// public override void Execute(IXPathNavigable contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, Stream results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, XmlWriter.Create(results, this.staticData.DefaultWriterSettings)); } ////// Executes the query by accessing datasources via the XmlResolver and using run-time parameters /// as provided by the XsltArgumentList. The default document is mapped into the XmlResolver with the /// provided name. The results are output to the provided XmlWriter. /// public void Execute(string contextDocumentUri, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocumentUri, dataSources, argumentList, results, false); } ////// Executes the query by accessing datasources via the XmlResolver and using /// run-time parameters as provided by the XsltArgumentList. The default document /// is mapped into the XmlResolver with the provided name. The results are returned /// as an IList. /// public IList Evaluate(string contextDocumentUri, XmlResolver dataSources, XsltArgumentList argumentList) { XmlCachedSequenceWriter seqwrt = new XmlCachedSequenceWriter(); Execute(contextDocumentUri, dataSources, argumentList, seqwrt); return seqwrt.ResultSequence; } ////// Executes the query by accessing datasources via the XmlResolver and using run-time parameters /// as provided by the XsltArgumentList. The default document is mapped into the XmlResolver with the /// provided name. The results are output to the provided XmlWriter. /// public override void Execute(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, results, false); } ////// Executes the query by accessing datasources via the XmlResolver and using run-time parameters /// as provided by the XsltArgumentList. The default document is mapped into the XmlResolver with the /// provided name. The results are output to the provided TextWriter. /// public override void Execute(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, TextWriter results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, XmlWriter.Create(results, this.staticData.DefaultWriterSettings), true); } ////// Executes the query by accessing datasources via the XmlResolver and using run-time parameters /// as provided by the XsltArgumentList. The default document is mapped into the XmlResolver with the /// provided name. The results are output to the provided Stream. /// public override void Execute(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList, Stream results) { if (results == null) throw new ArgumentNullException("results"); Execute(contextDocument, dataSources, argumentList, XmlWriter.Create(results, this.staticData.DefaultWriterSettings), true); } ////// Executes the query by accessing datasources via the XmlResolver and using /// run-time parameters as provided by the XsltArgumentList. The default document /// is mapped into the XmlResolver with the provided name. The results are returned /// as an IList. /// public override IList Evaluate(XmlReader contextDocument, XmlResolver dataSources, XsltArgumentList argumentList) { XmlCachedSequenceWriter seqwrt = new XmlCachedSequenceWriter(); Execute(contextDocument, dataSources, argumentList, seqwrt); return seqwrt.ResultSequence; } ////// Execute the dynamic assembly generated by the XmlILGenerator. /// private void Execute(object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlWriter writer, bool closeWriter) { try { // Try to extract a RawWriter XmlWellFormedWriter wellFormedWriter = writer as XmlWellFormedWriter; if (wellFormedWriter != null && wellFormedWriter.WriteState == WriteState.Start && wellFormedWriter.Settings.ConformanceLevel != ConformanceLevel.Document) { // Extracted RawWriter from WellFormedWriter Execute(defaultDocument, dataSources, argumentList, new XmlMergeSequenceWriter(wellFormedWriter.RawWriter)); } else { // Wrap Writer in RawWriter Execute(defaultDocument, dataSources, argumentList, new XmlMergeSequenceWriter(new XmlRawWriterWrapper(writer))); } } finally { // Close Writers that are created by XmlILGenerator; flush external writers if (closeWriter) writer.Close(); else writer.Flush(); } } ////// Execute the dynamic assembly generated by the XmlILGenerator. /// private void Execute(object defaultDocument, XmlResolver dataSources, XsltArgumentList argumentList, XmlSequenceWriter results) { Debug.Assert(results != null); // Ensure that dataSources is always non-null if (dataSources == null) dataSources = XmlNullResolver.Singleton; this.delExec(new XmlQueryRuntime(this.staticData, defaultDocument, dataSources, argumentList, results)); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- basecomparevalidator.cs
- IdleTimeoutMonitor.cs
- DefinitionUpdate.cs
- HttpApplicationFactory.cs
- TransportConfigurationTypeElementCollection.cs
- TrackingServices.cs
- DataBoundControlParameterTarget.cs
- ComplexLine.cs
- FtpWebRequest.cs
- ColumnHeader.cs
- OperationCanceledException.cs
- NavigationProperty.cs
- FunctionDetailsReader.cs
- IIS7UserPrincipal.cs
- ServerProtocol.cs
- QueryExecutionOption.cs
- WindowsScrollBarBits.cs
- RegexCompilationInfo.cs
- XmlReturnReader.cs
- KeyEvent.cs
- RemoteWebConfigurationHost.cs
- LogWriteRestartAreaState.cs
- StylusPointPropertyInfoDefaults.cs
- ItemCollection.cs
- EntityTransaction.cs
- HtmlTableRowCollection.cs
- StaticDataManager.cs
- adornercollection.cs
- EventPropertyMap.cs
- QueryCacheEntry.cs
- FixedSOMGroup.cs
- PeerCredential.cs
- SoapAttributeOverrides.cs
- BoolExpression.cs
- SqlProfileProvider.cs
- UniqueIdentifierService.cs
- Adorner.cs
- ThemeableAttribute.cs
- TableCellCollection.cs
- ErrorFormatter.cs
- CompositeDesignerAccessibleObject.cs
- XmlTextReader.cs
- MemoryStream.cs
- FileSystemWatcher.cs
- StringFormat.cs
- BookmarkEventArgs.cs
- XMLDiffLoader.cs
- DataGridViewLinkCell.cs
- Point3DCollectionValueSerializer.cs
- WindowsIdentity.cs
- BitConverter.cs
- ButtonBaseAutomationPeer.cs
- XPathAxisIterator.cs
- EntityDataSourceWizardForm.cs
- TrackingConditionCollection.cs
- BasePattern.cs
- InvalidDataException.cs
- DrawListViewItemEventArgs.cs
- SafeProcessHandle.cs
- ThreadStateException.cs
- VariableBinder.cs
- FormattedText.cs
- BitmapImage.cs
- BehaviorEditorPart.cs
- InputReportEventArgs.cs
- WmpBitmapEncoder.cs
- ColumnResizeAdorner.cs
- XslVisitor.cs
- Span.cs
- StretchValidation.cs
- CodeParameterDeclarationExpressionCollection.cs
- basevalidator.cs
- ComplexBindingPropertiesAttribute.cs
- DrawTreeNodeEventArgs.cs
- AdornerLayer.cs
- XmlSchemaExternal.cs
- SessionEndingCancelEventArgs.cs
- XmlRootAttribute.cs
- Propagator.JoinPropagator.cs
- DomainConstraint.cs
- HttpRequest.cs
- SelectionWordBreaker.cs
- RegexMatchCollection.cs
- SmiRecordBuffer.cs
- ComboBox.cs
- SortDescriptionCollection.cs
- SqlConnectionPoolGroupProviderInfo.cs
- _SecureChannel.cs
- SamlConstants.cs
- ConvertersCollection.cs
- Menu.cs
- IUnknownConstantAttribute.cs
- GridSplitter.cs
- UnsafeNativeMethods.cs
- ToolboxItem.cs
- SqlNamer.cs
- TextEditorCharacters.cs
- GetTokenRequest.cs
- PrinterSettings.cs
- cache.cs