Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / Microsoft / Scripting / Compiler / LambdaCompiler.Lambda.cs / 1305376 / LambdaCompiler.Lambda.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. * * * ***************************************************************************/ 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 { ////// Dynamic Language Runtime Compiler. /// This part compiles lambdas. /// partial class LambdaCompiler { private static int _Counter; internal void EmitConstantArray(T[] array) { // Emit as runtime constant if possible // if not, emit into IL if (_method is DynamicMethod) { EmitConstant(array, typeof(T[])); } else if(_typeBuilder != null) { // store into field in our type builder, we will initialize // the value only once. FieldBuilder fb = CreateStaticField("ConstantArray", typeof(T[])); Label l = _ilg.DefineLabel(); _ilg.Emit(OpCodes.Ldsfld, fb); _ilg.Emit(OpCodes.Ldnull); _ilg.Emit(OpCodes.Bne_Un, l); _ilg.EmitArray(array); _ilg.Emit(OpCodes.Stsfld, fb); _ilg.MarkLabel(l); _ilg.Emit(OpCodes.Ldsfld, fb); } else { _ilg.EmitArray(array); } } private void EmitClosureCreation(LambdaCompiler inner) { bool closure = inner._scope.NeedsClosure; bool boundConstants = inner._boundConstants.Count > 0; if (!closure && !boundConstants) { _ilg.EmitNull(); return; } // new Closure(constantPool, currentHoistedLocals) if (boundConstants) { _boundConstants.EmitConstant(this, inner._boundConstants.ToArray(), typeof(object[])); } else { _ilg.EmitNull(); } if (closure) { _scope.EmitGet(_scope.NearestHoistedLocals.SelfVariable); } else { _ilg.EmitNull(); } _ilg.EmitNew(typeof(Closure).GetConstructor(new Type[] { typeof(object[]), typeof(object[]) })); } /// /// Emits code which creates new instance of the delegateType delegate. /// /// Since the delegate is getting closed over the "Closure" argument, this /// cannot be used with virtual/instance methods (inner must be static method) /// private void EmitDelegateConstruction(LambdaCompiler inner) { Type delegateType = inner._lambda.Type; DynamicMethod dynamicMethod = inner._method as DynamicMethod; if (dynamicMethod != null) { // dynamicMethod.CreateDelegate(delegateType, closure) _boundConstants.EmitConstant(this, dynamicMethod, typeof(DynamicMethod)); _ilg.EmitType(delegateType); EmitClosureCreation(inner); _ilg.Emit(OpCodes.Callvirt, typeof(DynamicMethod).GetMethod("CreateDelegate", new Type[] { typeof(Type), typeof(object) })); _ilg.Emit(OpCodes.Castclass, delegateType); } else { // new DelegateType(closure) EmitClosureCreation(inner); _ilg.Emit(OpCodes.Ldftn, (MethodInfo)inner._method); _ilg.Emit(OpCodes.Newobj, (ConstructorInfo)(delegateType.GetMember(".ctor")[0])); } } ////// Emits a delegate to the method generated for the LambdaExpression. /// May end up creating a wrapper to match the requested delegate type. /// /// Lambda for which to generate a delegate /// private void EmitDelegateConstruction(LambdaExpression lambda) { // 1. Create the new compiler LambdaCompiler impl; if (_method is DynamicMethod) { impl = new LambdaCompiler(_tree, lambda); } else { // When the lambda does not have a name or the name is empty, generate a unique name for it. string name = String.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name; MethodBuilder mb = _typeBuilder.DefineMethod(name, MethodAttributes.Private | MethodAttributes.Static); impl = new LambdaCompiler(_tree, lambda, mb); } // 2. emit the lambda // Since additional ILs are always emitted after the lambda's body, should not emit with tail call optimization. impl.EmitLambdaBody(_scope, false, CompilationFlags.EmitAsNoTail); // 3. emit the delegate creation in the outer lambda EmitDelegateConstruction(impl); } private static Type[] GetParameterTypes(LambdaExpression lambda) { return lambda.Parameters.Map(p => p.IsByRef ? p.Type.MakeByRefType() : p.Type); } private static string GetUniqueMethodName() { return "{" + Interlocked.Increment(ref _Counter) + "}lambda_method"; } private void EmitLambdaBody() { // The lambda body is the "last" expression of the lambda CompilationFlags tailCallFlag = _lambda.TailCall ? CompilationFlags.EmitAsTail : CompilationFlags.EmitAsNoTail; EmitLambdaBody(null, false, tailCallFlag); } /// /// Emits the lambda body. If inlined, the parameters should already be /// pushed onto the IL stack. /// /// The parent scope. /// true if the lambda is inlined; false otherwise. /// /// The emum to specify if the lambda is compiled with the tail call optimization. /// private void EmitLambdaBody(CompilerScope parent, bool inlined, CompilationFlags flags) { _scope.Enter(this, parent); if (inlined) { // The arguments were already pushed onto the IL stack. // Store them into locals, popping in reverse order. // // If any arguments were ByRef, the address is on the stack and // we'll be storing it into the variable, which has a ref type. for (int i = _lambda.Parameters.Count - 1; i >= 0; i--) { _scope.EmitSet(_lambda.Parameters[i]); } } // Need to emit the expression start for the lambda body flags = UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitExpressionStart); if (_lambda.ReturnType == typeof(void)) { EmitExpressionAsVoid(_lambda.Body, flags); } else { EmitExpression(_lambda.Body, flags); } // Return must be the last instruction in a CLI method. // But if we're inlining the lambda, we want to leave the return // value on the IL stack. if (!inlined) { _ilg.Emit(OpCodes.Ret); } _scope.Exit(); // Validate labels Debug.Assert(_labelBlock.Parent == null && _labelBlock.Kind == LabelScopeKind.Lambda); foreach (LabelInfo label in _labelInfo.Values) { label.ValidateFinish(); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. /* **************************************************************************** * * 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. * * * ***************************************************************************/ 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 { ////// Dynamic Language Runtime Compiler. /// This part compiles lambdas. /// partial class LambdaCompiler { private static int _Counter; internal void EmitConstantArray(T[] array) { // Emit as runtime constant if possible // if not, emit into IL if (_method is DynamicMethod) { EmitConstant(array, typeof(T[])); } else if(_typeBuilder != null) { // store into field in our type builder, we will initialize // the value only once. FieldBuilder fb = CreateStaticField("ConstantArray", typeof(T[])); Label l = _ilg.DefineLabel(); _ilg.Emit(OpCodes.Ldsfld, fb); _ilg.Emit(OpCodes.Ldnull); _ilg.Emit(OpCodes.Bne_Un, l); _ilg.EmitArray(array); _ilg.Emit(OpCodes.Stsfld, fb); _ilg.MarkLabel(l); _ilg.Emit(OpCodes.Ldsfld, fb); } else { _ilg.EmitArray(array); } } private void EmitClosureCreation(LambdaCompiler inner) { bool closure = inner._scope.NeedsClosure; bool boundConstants = inner._boundConstants.Count > 0; if (!closure && !boundConstants) { _ilg.EmitNull(); return; } // new Closure(constantPool, currentHoistedLocals) if (boundConstants) { _boundConstants.EmitConstant(this, inner._boundConstants.ToArray(), typeof(object[])); } else { _ilg.EmitNull(); } if (closure) { _scope.EmitGet(_scope.NearestHoistedLocals.SelfVariable); } else { _ilg.EmitNull(); } _ilg.EmitNew(typeof(Closure).GetConstructor(new Type[] { typeof(object[]), typeof(object[]) })); } /// /// Emits code which creates new instance of the delegateType delegate. /// /// Since the delegate is getting closed over the "Closure" argument, this /// cannot be used with virtual/instance methods (inner must be static method) /// private void EmitDelegateConstruction(LambdaCompiler inner) { Type delegateType = inner._lambda.Type; DynamicMethod dynamicMethod = inner._method as DynamicMethod; if (dynamicMethod != null) { // dynamicMethod.CreateDelegate(delegateType, closure) _boundConstants.EmitConstant(this, dynamicMethod, typeof(DynamicMethod)); _ilg.EmitType(delegateType); EmitClosureCreation(inner); _ilg.Emit(OpCodes.Callvirt, typeof(DynamicMethod).GetMethod("CreateDelegate", new Type[] { typeof(Type), typeof(object) })); _ilg.Emit(OpCodes.Castclass, delegateType); } else { // new DelegateType(closure) EmitClosureCreation(inner); _ilg.Emit(OpCodes.Ldftn, (MethodInfo)inner._method); _ilg.Emit(OpCodes.Newobj, (ConstructorInfo)(delegateType.GetMember(".ctor")[0])); } } ////// Emits a delegate to the method generated for the LambdaExpression. /// May end up creating a wrapper to match the requested delegate type. /// /// Lambda for which to generate a delegate /// private void EmitDelegateConstruction(LambdaExpression lambda) { // 1. Create the new compiler LambdaCompiler impl; if (_method is DynamicMethod) { impl = new LambdaCompiler(_tree, lambda); } else { // When the lambda does not have a name or the name is empty, generate a unique name for it. string name = String.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name; MethodBuilder mb = _typeBuilder.DefineMethod(name, MethodAttributes.Private | MethodAttributes.Static); impl = new LambdaCompiler(_tree, lambda, mb); } // 2. emit the lambda // Since additional ILs are always emitted after the lambda's body, should not emit with tail call optimization. impl.EmitLambdaBody(_scope, false, CompilationFlags.EmitAsNoTail); // 3. emit the delegate creation in the outer lambda EmitDelegateConstruction(impl); } private static Type[] GetParameterTypes(LambdaExpression lambda) { return lambda.Parameters.Map(p => p.IsByRef ? p.Type.MakeByRefType() : p.Type); } private static string GetUniqueMethodName() { return "{" + Interlocked.Increment(ref _Counter) + "}lambda_method"; } private void EmitLambdaBody() { // The lambda body is the "last" expression of the lambda CompilationFlags tailCallFlag = _lambda.TailCall ? CompilationFlags.EmitAsTail : CompilationFlags.EmitAsNoTail; EmitLambdaBody(null, false, tailCallFlag); } /// /// Emits the lambda body. If inlined, the parameters should already be /// pushed onto the IL stack. /// /// The parent scope. /// true if the lambda is inlined; false otherwise. /// /// The emum to specify if the lambda is compiled with the tail call optimization. /// private void EmitLambdaBody(CompilerScope parent, bool inlined, CompilationFlags flags) { _scope.Enter(this, parent); if (inlined) { // The arguments were already pushed onto the IL stack. // Store them into locals, popping in reverse order. // // If any arguments were ByRef, the address is on the stack and // we'll be storing it into the variable, which has a ref type. for (int i = _lambda.Parameters.Count - 1; i >= 0; i--) { _scope.EmitSet(_lambda.Parameters[i]); } } // Need to emit the expression start for the lambda body flags = UpdateEmitExpressionStartFlag(flags, CompilationFlags.EmitExpressionStart); if (_lambda.ReturnType == typeof(void)) { EmitExpressionAsVoid(_lambda.Body, flags); } else { EmitExpression(_lambda.Body, flags); } // Return must be the last instruction in a CLI method. // But if we're inlining the lambda, we want to leave the return // value on the IL stack. if (!inlined) { _ilg.Emit(OpCodes.Ret); } _scope.Exit(); // Validate labels Debug.Assert(_labelBlock.Parent == null && _labelBlock.Kind == LabelScopeKind.Lambda); foreach (LabelInfo label in _labelInfo.Values) { label.ValidateFinish(); } } } } // 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
- SafeWaitHandle.cs
- CompensatableSequenceActivity.cs
- HttpModulesSection.cs
- Model3DGroup.cs
- XmlMessageFormatter.cs
- BrowserCapabilitiesFactoryBase.cs
- CodeDirectiveCollection.cs
- Int32KeyFrameCollection.cs
- RootBuilder.cs
- MapPathBasedVirtualPathProvider.cs
- RegexGroupCollection.cs
- SetIterators.cs
- BitmapFrame.cs
- BooleanFunctions.cs
- ISO2022Encoding.cs
- QilLiteral.cs
- CodeTypeParameter.cs
- TableLayoutPanelCellPosition.cs
- WebHttpBehavior.cs
- AccessibleObject.cs
- TextBlockAutomationPeer.cs
- XXXOnTypeBuilderInstantiation.cs
- uribuilder.cs
- TimeZone.cs
- ReadOnlyObservableCollection.cs
- Page.cs
- glyphs.cs
- SelectionItemProviderWrapper.cs
- UnmanagedHandle.cs
- TreeNodeConverter.cs
- Stroke.cs
- TdsEnums.cs
- SafeWaitHandle.cs
- IntSecurity.cs
- PositiveTimeSpanValidator.cs
- FlowNode.cs
- PolyBezierSegment.cs
- GeneratedCodeAttribute.cs
- BinaryObjectWriter.cs
- Sorting.cs
- BaseAddressElement.cs
- WebDescriptionAttribute.cs
- AssociationSetEnd.cs
- ExceptionHelpers.cs
- ArglessEventHandlerProxy.cs
- SystemDropShadowChrome.cs
- DataGridViewColumnDesignTimeVisibleAttribute.cs
- Binding.cs
- SelectedGridItemChangedEvent.cs
- SubclassTypeValidatorAttribute.cs
- ListViewUpdatedEventArgs.cs
- ManifestSignedXml.cs
- ExternalException.cs
- TextOutput.cs
- DivideByZeroException.cs
- SqlCacheDependencyDatabase.cs
- WebPartCloseVerb.cs
- LongAverageAggregationOperator.cs
- ComMethodElementCollection.cs
- DataGridViewElement.cs
- ListBase.cs
- ToolStripItemRenderEventArgs.cs
- WeakEventManager.cs
- HttpCachePolicyBase.cs
- StopStoryboard.cs
- ConfigDefinitionUpdates.cs
- DrawingGroup.cs
- SqlBuffer.cs
- CustomPopupPlacement.cs
- SmiContextFactory.cs
- ThrowHelper.cs
- HyperLinkColumn.cs
- LogEntrySerializationException.cs
- ProfileBuildProvider.cs
- MetaModel.cs
- ProfileModule.cs
- XmlTypeAttribute.cs
- TextBreakpoint.cs
- FixedDocument.cs
- NullableDecimalSumAggregationOperator.cs
- FormatException.cs
- SyndicationPerson.cs
- AutoFocusStyle.xaml.cs
- PointCollection.cs
- DesignerMetadata.cs
- CryptographicAttribute.cs
- ManipulationDevice.cs
- ToolStripAdornerWindowService.cs
- Vector.cs
- XmlWrappingWriter.cs
- MatrixAnimationUsingKeyFrames.cs
- DbParameterCollection.cs
- ValuePattern.cs
- BaseCodeDomTreeGenerator.cs
- PropertyValueChangedEvent.cs
- MenuDesigner.cs
- FlowPosition.cs
- documentsequencetextpointer.cs
- BuilderInfo.cs
- InputLanguageManager.cs