Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Compiler / LambdaCompiler.cs / 1305376 / LambdaCompiler.cs
/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Microsoft Public License. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Microsoft Public License, please send an email to * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Microsoft Public License. * * You must not remove this notice, or any other, from this software. * * * ***************************************************************************/ #if MICROSOFT_SCRIPTING_CORE || SILVERLIGHT using ILGenerator = System.Linq.Expressions.Compiler.OffsetTrackingILGenerator; #endif using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Dynamic.Utils; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Threading; namespace System.Linq.Expressions.Compiler { ////// LambdaCompiler is responsible for compiling individual lambda (LambdaExpression). The complete tree may /// contain multiple lambdas, the Compiler class is reponsible for compiling the whole tree, individual /// lambdas are then compiled by the LambdaCompiler. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")] internal sealed partial class LambdaCompiler { private delegate void WriteBack(); // Information on the entire lambda tree currently being compiled private readonly AnalyzedTree _tree; private readonly ILGenerator _ilg; // The TypeBuilder backing this method, if any private readonly TypeBuilder _typeBuilder; private readonly MethodInfo _method; // Currently active LabelTargets and their mapping to IL labels private LabelScopeInfo _labelBlock = new LabelScopeInfo(null, LabelScopeKind.Lambda); // Mapping of labels used for "long" jumps (jumping out and into blocks) private readonly Dictionary_labelInfo = new Dictionary (); // The currently active variable scope private CompilerScope _scope; // The lambda we are compiling private readonly LambdaExpression _lambda; // True if the method's first argument is of type Closure private readonly bool _hasClosureArgument; // True if we want to emitting debug symbols private bool EmitDebugSymbols { get { return _tree.DebugInfoGenerator != null; } } // Runtime constants bound to the delegate private readonly BoundConstants _boundConstants; // Free list of locals, so we reuse them rather than creating new ones private readonly KeyedQueue _freeLocals = new KeyedQueue (); /// /// The value is true if a clearance was emitted and no new sequence point /// has been emitted since that. /// bool _sequencePointCleared; ////// Creates a lambda compiler that will compile to a dynamic method /// private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda) { Type[] parameterTypes = GetParameterTypes(lambda).AddFirst(typeof(Closure)); #if SILVERLIGHT && MICROSOFT_SCRIPTING_CORE var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes); #else var method = new DynamicMethod(lambda.Name ?? "lambda_method", lambda.ReturnType, parameterTypes, true); #endif _tree = tree; _lambda = lambda; _method = method; #if MICROSOFT_SCRIPTING_CORE || SILVERLIGHT _ilg = new OffsetTrackingILGenerator(method.GetILGenerator()); #else _ilg = method.GetILGenerator(); #endif _hasClosureArgument = true; // These are populated by AnalyzeTree/VariableBinder _scope = tree.Scopes[lambda]; _boundConstants = tree.Constants[lambda]; InitializeMethod(); } ////// Creates a lambda compiler that will compile into the provided Methodbuilder /// private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method) { _hasClosureArgument = tree.Scopes[lambda].NeedsClosure; Type[] paramTypes = GetParameterTypes(lambda); if (_hasClosureArgument) { paramTypes = paramTypes.AddFirst(typeof(Closure)); } method.SetReturnType(lambda.ReturnType); method.SetParameters(paramTypes); var paramNames = lambda.Parameters.Map(p => p.Name); // parameters are index from 1, with closure argument we need to skip the first arg int startIndex = _hasClosureArgument ? 2 : 1; for (int i = 0; i < paramNames.Length; i++) { method.DefineParameter(i + startIndex, ParameterAttributes.None, paramNames[i]); } _tree = tree; _lambda = lambda; _typeBuilder = (TypeBuilder)method.DeclaringType; _method = method; #if MICROSOFT_SCRIPTING_CORE || SILVERLIGHT _ilg = new OffsetTrackingILGenerator(method.GetILGenerator()); #else _ilg = method.GetILGenerator(); #endif // These are populated by AnalyzeTree/VariableBinder _scope = tree.Scopes[lambda]; _boundConstants = tree.Constants[lambda]; InitializeMethod(); } ////// Creates a lambda compiler for an inlined lambda /// private LambdaCompiler(LambdaCompiler parent, LambdaExpression lambda) { _tree = parent._tree; _lambda = lambda; _method = parent._method; _ilg = parent._ilg; _hasClosureArgument = parent._hasClosureArgument; _typeBuilder = parent._typeBuilder; _scope = _tree.Scopes[lambda]; _boundConstants = parent._boundConstants; } private void InitializeMethod() { // See if we can find a return label, so we can emit better IL AddReturnLabel(_lambda); _boundConstants.EmitCacheConstants(this); } public override string ToString() { return _method.ToString(); } internal ILGenerator IL { get { return _ilg; } } internal ReadOnlyCollectionParameters { get { return _lambda.Parameters; } } internal bool CanEmitBoundConstants { get { return _method is DynamicMethod; } } #region Compiler entry points /// /// Compiler entry point /// /// LambdaExpression to compile. /// Debug info generator. ///The compiled delegate. internal static Delegate Compile(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator) { // 1. Bind lambda AnalyzedTree tree = AnalyzeLambda(ref lambda); tree.DebugInfoGenerator = debugInfoGenerator; // 2. Create lambda compiler LambdaCompiler c = new LambdaCompiler(tree, lambda); // 3. Emit c.EmitLambdaBody(); // 4. Return the delegate. return c.CreateDelegate(); } ////// Mutates the MethodBuilder parameter, filling in IL, parameters, /// and return type. /// /// (probably shouldn't be modifying parameters/return type...) /// internal static void Compile(LambdaExpression lambda, MethodBuilder method, DebugInfoGenerator debugInfoGenerator) { // 1. Bind lambda AnalyzedTree tree = AnalyzeLambda(ref lambda); tree.DebugInfoGenerator = debugInfoGenerator; // 2. Create lambda compiler LambdaCompiler c = new LambdaCompiler(tree, lambda, method); // 3. Emit c.EmitLambdaBody(); } #endregion private static AnalyzedTree AnalyzeLambda(ref LambdaExpression lambda) { // Spill the stack for any exception handling blocks or other // constructs which require entering with an empty stack lambda = StackSpiller.AnalyzeLambda(lambda); // Bind any variable references in this lambda return VariableBinder.Bind(lambda); } internal LocalBuilder GetLocal(Type type) { Debug.Assert(type != null); LocalBuilder local; if (_freeLocals.TryDequeue(type, out local)) { Debug.Assert(type == local.LocalType); return local; } return _ilg.DeclareLocal(type); } internal void FreeLocal(LocalBuilder local) { if (local != null) { _freeLocals.Enqueue(local.LocalType, local); } } internal LocalBuilder GetNamedLocal(Type type, ParameterExpression variable) { Debug.Assert(type != null && variable != null); LocalBuilder lb = _ilg.DeclareLocal(type); if (EmitDebugSymbols && variable.Name != null) { _tree.DebugInfoGenerator.SetLocalName(lb, variable.Name); } return lb; } ////// Gets the argument slot corresponding to the parameter at the given /// index. Assumes that the method takes a certain number of prefix /// arguments, followed by the real parameters stored in Parameters /// internal int GetLambdaArgument(int index) { return index + (_hasClosureArgument ? 1 : 0) + (_method.IsStatic ? 0 : 1); } ////// Returns the index-th argument. This method provides access to the actual arguments /// defined on the lambda itself, and excludes the possible 0-th closure argument. /// internal void EmitLambdaArgument(int index) { _ilg.EmitLoadArg(GetLambdaArgument(index)); } internal void EmitClosureArgument() { Debug.Assert(_hasClosureArgument, "must have a Closure argument"); Debug.Assert(_method.IsStatic, "must be a static method"); _ilg.EmitLoadArg(0); } private Delegate CreateDelegate() { Debug.Assert(_method is DynamicMethod); return _method.CreateDelegate(_lambda.Type, new Closure(_boundConstants.ToArray(), null)); } private FieldBuilder CreateStaticField(string name, Type type) { // We are emitting into someone else's type. We don't want name // conflicts, so choose a long name that is unlikely to confict. // Naming scheme chosen here is similar to what the C# compiler // uses. return _typeBuilder.DefineField("{" + Interlocked.Increment(ref _Counter) + "}" + name, type, FieldAttributes.Static | FieldAttributes.Private); } /// /// Creates an unitialized field suitible for private implementation details /// Works with DynamicMethods or TypeBuilders. /// private MemberExpression CreateLazyInitializedField(string name) { if (_method is DynamicMethod) { return Expression.Field(Expression.Constant(new StrongBox ()), "Value"); } else { return Expression.Field(null, CreateStaticField(name, typeof(T))); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataGridTablesFactory.cs
- TransformDescriptor.cs
- Transform3DGroup.cs
- PrimarySelectionGlyph.cs
- DbProviderFactory.cs
- Transform3D.cs
- AssemblyAttributes.cs
- BitStack.cs
- MouseActionValueSerializer.cs
- XsdValidatingReader.cs
- WebPartEditorOkVerb.cs
- ButtonStandardAdapter.cs
- WebScriptMetadataFormatter.cs
- propertyentry.cs
- UInt64.cs
- JavaScriptSerializer.cs
- Italic.cs
- TypeDescriptionProvider.cs
- WindowsMenu.cs
- XmlResolver.cs
- DbProviderConfigurationHandler.cs
- ViewKeyConstraint.cs
- SqlUserDefinedTypeAttribute.cs
- PropertyEntry.cs
- bindurihelper.cs
- CompiledQuery.cs
- DescendantOverDescendantQuery.cs
- BindingBase.cs
- Documentation.cs
- HttpCookieCollection.cs
- OleDbEnumerator.cs
- BindingNavigator.cs
- GridItem.cs
- IProvider.cs
- WebResourceUtil.cs
- StrongNameUtility.cs
- StyleCollection.cs
- DBSqlParser.cs
- XmlCustomFormatter.cs
- ValueTypeFixupInfo.cs
- LocalizedNameDescriptionPair.cs
- Attributes.cs
- SpoolingTask.cs
- ValidationError.cs
- SystemTcpConnection.cs
- AssemblyBuilderData.cs
- Cursors.cs
- DataSourceProvider.cs
- HorizontalAlignConverter.cs
- InstanceDescriptor.cs
- CommonDialog.cs
- XslAst.cs
- AnonymousIdentificationModule.cs
- SocketInformation.cs
- CodeGeneratorOptions.cs
- MoveSizeWinEventHandler.cs
- DESCryptoServiceProvider.cs
- HttpRuntimeSection.cs
- SafeCertificateContext.cs
- ToolStripItemRenderEventArgs.cs
- TableRowCollection.cs
- MailMessageEventArgs.cs
- SmiSettersStream.cs
- ListViewCommandEventArgs.cs
- X509ClientCertificateAuthentication.cs
- ObjectKeyFrameCollection.cs
- DelegatingConfigHost.cs
- XmlConvert.cs
- ListViewSelectEventArgs.cs
- HelpProvider.cs
- ToolboxBitmapAttribute.cs
- BinaryHeap.cs
- ObjectStateManager.cs
- PointConverter.cs
- ControlIdConverter.cs
- BulletedListEventArgs.cs
- UIPermission.cs
- MediaTimeline.cs
- WebBrowserDocumentCompletedEventHandler.cs
- XmlTextAttribute.cs
- DateTimeSerializationSection.cs
- LazyTextWriterCreator.cs
- XmlReturnWriter.cs
- ItemList.cs
- ObjectListField.cs
- AutomationPeer.cs
- VarRefManager.cs
- TreeViewEvent.cs
- TypeHelpers.cs
- DataGridDefaultColumnWidthTypeConverter.cs
- GrammarBuilderPhrase.cs
- ToolStripKeyboardHandlingService.cs
- Thickness.cs
- InkCanvasAutomationPeer.cs
- BitSet.cs
- XsltContext.cs
- AttachedAnnotation.cs
- HtmlEmptyTagControlBuilder.cs
- StandardBindingOptionalReliableSessionElement.cs
- Marshal.cs