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
- MenuRenderer.cs
- SchemaImporterExtensionElement.cs
- AccessDataSourceView.cs
- RootBrowserWindow.cs
- CodeSnippetStatement.cs
- VarRefManager.cs
- MsmqIntegrationBinding.cs
- HandoffBehavior.cs
- XmlIncludeAttribute.cs
- SiteMap.cs
- SimpleLine.cs
- AttachmentService.cs
- EditingScope.cs
- ColorConverter.cs
- RepeaterCommandEventArgs.cs
- ResourceDictionary.cs
- NotifyIcon.cs
- StringPropertyBuilder.cs
- ToolStrip.cs
- TypeUtils.cs
- CompilerLocalReference.cs
- StoreContentChangedEventArgs.cs
- Latin1Encoding.cs
- StyleCollection.cs
- DataGridViewRowCollection.cs
- TypeContext.cs
- SmiEventSink_Default.cs
- SQLDateTime.cs
- SequenceFullException.cs
- CodeCatchClause.cs
- WebServiceErrorEvent.cs
- MetaColumn.cs
- ResourceContainer.cs
- ParseChildrenAsPropertiesAttribute.cs
- SiteIdentityPermission.cs
- CookielessData.cs
- PointHitTestParameters.cs
- FileDetails.cs
- SafeHandles.cs
- Label.cs
- EventRecord.cs
- CustomLineCap.cs
- SafeNativeMethods.cs
- RolePrincipal.cs
- HeaderUtility.cs
- DSASignatureDeformatter.cs
- DesignBindingPropertyDescriptor.cs
- DbModificationClause.cs
- PassportPrincipal.cs
- MethodBuilder.cs
- RequestCachePolicy.cs
- SizeValueSerializer.cs
- WebHeaderCollection.cs
- AdvancedBindingPropertyDescriptor.cs
- Helper.cs
- DataGridViewIntLinkedList.cs
- mediaclock.cs
- ClientApiGenerator.cs
- RequestCache.cs
- VBCodeProvider.cs
- TextEffect.cs
- MethodBody.cs
- XPathNodeInfoAtom.cs
- ControlOperationInvoker.cs
- ErasingStroke.cs
- CollectionDataContract.cs
- XmlSchemaSimpleContentExtension.cs
- MetadataItemSerializer.cs
- Parser.cs
- TextStore.cs
- ProviderBase.cs
- ClientTargetSection.cs
- GenericUI.cs
- BinaryObjectInfo.cs
- MexBindingBindingCollectionElement.cs
- BuildManagerHost.cs
- CodeCatchClause.cs
- SystemUdpStatistics.cs
- TreeNodeClickEventArgs.cs
- initElementDictionary.cs
- SoapReflectionImporter.cs
- OleDbParameterCollection.cs
- Rotation3DAnimationUsingKeyFrames.cs
- MobileDeviceCapabilitiesSectionHandler.cs
- Rotation3D.cs
- WebControl.cs
- Ref.cs
- TypeHelpers.cs
- EntityDataSourceState.cs
- _DigestClient.cs
- WebPartZoneCollection.cs
- AttributeData.cs
- WebPartConnectionsEventArgs.cs
- AddressAlreadyInUseException.cs
- PrivateUnsafeNativeCompoundFileMethods.cs
- LinqDataSourceView.cs
- AsymmetricSignatureFormatter.cs
- KeySplineConverter.cs
- TabRenderer.cs
- MediaElement.cs