The Labs \ Source Viewer \ SSCLI \ System.Reflection.Emit \ VarArgMethod

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Reflection.Emit
  16. {
  17.    
  18.     using System;
  19.     using System.Globalization;
  20.     using TextWriter = System.IO.TextWriter;
  21.     using System.Diagnostics.SymbolStore;
  22.     using System.Runtime.InteropServices;
  23.     using System.Reflection;
  24.     using System.Collections;
  25.     using System.Security.Permissions;
  26.    
  27.     internal class DynamicILGenerator : ILGenerator
  28.     {
  29.        
  30.         internal DynamicScope m_scope;
  31.         private int m_methodSigToken;
  32.        
  33.         unsafe internal DynamicILGenerator(DynamicMethod method, byte[] methodSignature, int size) : base(method, size)
  34.         {
  35.             m_scope = new DynamicScope();
  36.             m_methodSigToken = m_scope.GetTokenFor(methodSignature);
  37.         }
  38.        
  39.        
  40.         unsafe internal RuntimeMethodHandle GetCallableMethod(void* module)
  41.         {
  42.             return new RuntimeMethodHandle(ModuleHandle.GetDynamicMethod(module, m_methodBuilder.Name, (byte[])m_scope[m_methodSigToken], new DynamicResolver(this)));
  43.         }
  44.        
  45.         // *** ILGenerator api ***
  46.        
  47.         public override LocalBuilder DeclareLocal(Type localType, bool pinned)
  48.         {
  49.             LocalBuilder localBuilder;
  50.             if (localType == null)
  51.                 throw new ArgumentNullException("localType");
  52.             if (localType.GetType() != typeof(RuntimeType))
  53.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
  54.             localBuilder = new LocalBuilder(m_localCount, localType, m_methodBuilder);
  55.             // add the localType to local signature
  56.             m_localSignature.AddArgument(localType, pinned);
  57.             m_localCount++;
  58.             return localBuilder;
  59.         }
  60.        
  61.         //
  62.         //
  63.         // Token resolution calls
  64.         //
  65.         //
  66.         public override void Emit(OpCode opcode, MethodInfo meth)
  67.         {
  68.             if (meth == null)
  69.                 throw new ArgumentNullException("meth");
  70.            
  71.             int stackchange = 0;
  72.             int tempVal = 0;
  73.             DynamicMethod dynMeth = DynamicMethod.AsDynamicMethod(meth);
  74.             if (dynMeth == null) {
  75.                 if (!(meth is RuntimeMethodInfo))
  76.                     throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "meth");
  77.                
  78.                 if (meth.DeclaringType != null && (meth.DeclaringType.IsGenericType || meth.DeclaringType.IsArray))
  79.                     tempVal = m_scope.GetTokenFor(meth.MethodHandle, meth.DeclaringType.TypeHandle);
  80.                 else
  81.                     tempVal = m_scope.GetTokenFor(meth.MethodHandle);
  82.             }
  83.             else {
  84.                 // rule out not allowed operations on DynamicMethods
  85.                 if (opcode.Equals(OpCodes.Ldtoken) || opcode.Equals(OpCodes.Ldftn) || opcode.Equals(OpCodes.Ldvirtftn)) {
  86.                     throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOpCodeOnDynamicMethod"));
  87.                 }
  88.                 tempVal = m_scope.GetTokenFor(dynMeth);
  89.             }
  90.            
  91.             EnsureCapacity(7);
  92.             InternalEmit(opcode);
  93.            
  94.             if (opcode.m_push == StackBehaviour.Varpush && meth.ReturnType != typeof(void)) {
  95.                 stackchange++;
  96.             }
  97.             if (opcode.m_pop == StackBehaviour.Varpop) {
  98.                 stackchange -= meth.GetParametersNoCopy().Length;
  99.             }
  100.             // Pop the "this" parameter if the method is non-static,
  101.             // and the instruction is not newobj/ldtoken/ldftn.
  102.             if (!meth.IsStatic && !(opcode.Equals(OpCodes.Newobj) || opcode.Equals(OpCodes.Ldtoken) || opcode.Equals(OpCodes.Ldftn))) {
  103.                 stackchange--;
  104.             }
  105.            
  106.             UpdateStackSize(opcode, stackchange);
  107.            
  108.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  109.         }
  110.        
  111.         [System.Runtime.InteropServices.ComVisible(true)]
  112.         public override void Emit(OpCode opcode, ConstructorInfo con)
  113.         {
  114.             if (con == null || !(con is RuntimeConstructorInfo))
  115.                 throw new ArgumentNullException("con");
  116.             if (con.DeclaringType != null && con.DeclaringType.IsGenericType)
  117.                 Emit(opcode, con.MethodHandle, con.DeclaringType.TypeHandle);
  118.             else
  119.                 Emit(opcode, con.MethodHandle);
  120.         }
  121.        
  122.         public void Emit(OpCode opcode, RuntimeMethodHandle meth)
  123.         {
  124.             if (meth.IsNullHandle())
  125.                 throw new ArgumentNullException("meth");
  126.            
  127.             // need to sort out the stack size story
  128.             //int stackchange = 0;
  129.             int tempVal = m_scope.GetTokenFor(meth);
  130.             EnsureCapacity(7);
  131.             InternalEmit(opcode);
  132.            
  133.             // need to sort out the stack size story
  134.             /*
  135.             if (opcode.m_push == StackBehaviour.Varpush
  136.                 && meth.ReturnType != typeof(void)) { stackchange++; }
  137.             if (opcode.m_pop  == StackBehaviour.Varpop) {
  138.               stackchange -= meth.GetParametersNoCopy().Length; }
  139.             if (!meth.IsStatic && !(opcode.Equals(OpCodes.Newobj))) {stackchange--; }
  140.            
  141.             UpdateStackSize(opcode, stackchange);
  142.             */           
  143.             // need to sort out the stack size story
  144. UpdateStackSize(opcode, 1);
  145.            
  146.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  147.         }
  148.        
  149.         public void Emit(OpCode opcode, RuntimeMethodHandle meth, RuntimeTypeHandle typeContext)
  150.         {
  151.             if (meth.IsNullHandle())
  152.                 throw new ArgumentNullException("meth");
  153.             if (typeContext.IsNullHandle())
  154.                 throw new ArgumentNullException("typeContext");
  155.            
  156.             // need to sort out the stack size story
  157.             //int stackchange = 0;
  158.             int tempVal = m_scope.GetTokenFor(meth, typeContext);
  159.             EnsureCapacity(7);
  160.             InternalEmit(opcode);
  161.            
  162.             // need to sort out the stack size story
  163.             /*
  164.             if (opcode.m_push == StackBehaviour.Varpush
  165.                 && meth.ReturnType != typeof(void)) { stackchange++; }
  166.             if (opcode.m_pop  == StackBehaviour.Varpop) {
  167.               stackchange -= meth.GetParametersNoCopy().Length; }
  168.             if (!meth.IsStatic && !(opcode.Equals(OpCodes.Newobj))) {stackchange--; }
  169.            
  170.             UpdateStackSize(opcode, stackchange);
  171.             */           
  172.             // need to sort out the stack size story
  173. UpdateStackSize(opcode, 1);
  174.            
  175.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  176.         }
  177.        
  178.         public override void Emit(OpCode opcode, Type type)
  179.         {
  180.             if (type == null)
  181.                 throw new ArgumentNullException("type");
  182.             Emit(opcode, type.TypeHandle);
  183.         }
  184.        
  185.         public void Emit(OpCode opcode, RuntimeTypeHandle typeHandle)
  186.         {
  187.             if (typeHandle.IsNullHandle())
  188.                 throw new ArgumentNullException("typeHandle");
  189.            
  190.             int tempVal = m_scope.GetTokenFor(typeHandle);
  191.             EnsureCapacity(7);
  192.             InternalEmit(opcode);
  193.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  194.         }
  195.        
  196.         public override void Emit(OpCode opcode, FieldInfo field)
  197.         {
  198.             if (field == null)
  199.                 throw new ArgumentNullException("field");
  200.             if (!(field is RuntimeFieldInfo))
  201.                 throw new ArgumentNullException("field");
  202.             Emit(opcode, field.FieldHandle);
  203.         }
  204.        
  205.         public void Emit(OpCode opcode, RuntimeFieldHandle fieldHandle)
  206.         {
  207.             if (fieldHandle.IsNullHandle())
  208.                 throw new ArgumentNullException("fieldHandle");
  209.            
  210.             int tempVal = m_scope.GetTokenFor(fieldHandle);
  211.             EnsureCapacity(7);
  212.             InternalEmit(opcode);
  213.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  214.         }
  215.        
  216.         public override void Emit(OpCode opcode, string str)
  217.         {
  218.             if (str == null)
  219.                 throw new ArgumentNullException("str");
  220.            
  221.             int tempVal = AddStringLiteral(str);
  222.             tempVal = tempVal | 1879048192;
  223.             EnsureCapacity(7);
  224.             InternalEmit(opcode);
  225.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  226.         }
  227.        
  228.         //
  229.         //
  230.         // Signature related calls (vararg, calli)
  231.         //
  232.         //
  233.         public override void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
  234.         {
  235.             int stackchange = 0;
  236.             SignatureHelper sig;
  237.             if (optionalParameterTypes != null)
  238.                 if ((callingConvention & CallingConventions.VarArgs) == 0)
  239.                
  240.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention"));
  241.            
  242.             sig = GetMemberRefSignature(callingConvention, returnType, parameterTypes, optionalParameterTypes);
  243.            
  244.             EnsureCapacity(7);
  245.             Emit(OpCodes.Calli);
  246.            
  247.             // The opcode passed in must be the calli instruction.
  248.             BCLDebug.Assert(opcode.Equals(OpCodes.Calli), "Unexpected opcode passed to EmitCalli.");
  249.             // If there is a non-void return type, push one.
  250.             if (returnType != typeof(void))
  251.                 stackchange++;
  252.             // Pop off arguments if any.
  253.             if (parameterTypes != null)
  254.                 stackchange -= parameterTypes.Length;
  255.             // Pop off vararg arguments.
  256.             if (optionalParameterTypes != null)
  257.                 stackchange -= optionalParameterTypes.Length;
  258.             // Pop the this parameter if the method has a this parameter.
  259.             if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
  260.                 stackchange--;
  261.             // Pop the native function pointer.
  262.             stackchange--;
  263.             UpdateStackSize(opcode, stackchange);
  264.            
  265.             int token = AddSignature(sig.GetSignature(true));
  266.             m_length = PutInteger4(token, m_length, m_ILStream);
  267.         }
  268.        
  269.         public override void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes)
  270.         {
  271.             int stackchange = 0;
  272.             int cParams = 0;
  273.             int i;
  274.             SignatureHelper sig;
  275.            
  276.             // The opcode passed in must be the calli instruction.
  277.             BCLDebug.Assert(opcode.Equals(OpCodes.Calli), "Unexpected opcode passed to EmitCalli.");
  278.             if (parameterTypes != null)
  279.                 cParams = parameterTypes.Length;
  280.            
  281.             sig = SignatureHelper.GetMethodSigHelper(unmanagedCallConv, returnType);
  282.            
  283.             if (parameterTypes != null)
  284.                 for (i = 0; i < cParams; i++)
  285.                     sig.AddArgument(parameterTypes[i]);
  286.            
  287.             // If there is a non-void return type, push one.
  288.             if (returnType != typeof(void))
  289.                 stackchange++;
  290.            
  291.             // Pop off arguments if any.
  292.             if (parameterTypes != null)
  293.                 stackchange -= cParams;
  294.            
  295.             // Pop the native function pointer.
  296.             stackchange--;
  297.             UpdateStackSize(opcode, stackchange);
  298.            
  299.             EnsureCapacity(7);
  300.             Emit(OpCodes.Calli);
  301.             int token = AddSignature(sig.GetSignature(true));
  302.             m_length = PutInteger4(token, m_length, m_ILStream);
  303.         }
  304.        
  305.         public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)
  306.         {
  307.             int tk;
  308.             int stackchange = 0;
  309.            
  310.             if (methodInfo == null)
  311.                 throw new ArgumentNullException("methodInfo");
  312.            
  313.             if (methodInfo.ContainsGenericParameters)
  314.                 throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "methodInfo");
  315.            
  316.             if (methodInfo.DeclaringType != null && methodInfo.DeclaringType.ContainsGenericParameters)
  317.                 throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "methodInfo");
  318.            
  319.             tk = GetMemberRefToken(methodInfo, optionalParameterTypes);
  320.            
  321.             EnsureCapacity(7);
  322.             InternalEmit(opcode);
  323.            
  324.             // The opcode must be one of call, callvirt, or newobj.
  325.             BCLDebug.Assert(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj), "Unexpected opcode passed to EmitCall.");
  326.            
  327.             // Push the return value if there is one.
  328.             if (methodInfo.ReturnType != typeof(void))
  329.                 stackchange++;
  330.             // Pop the parameters.
  331.             stackchange -= methodInfo.GetParameterTypes().Length;
  332.             // Pop the this parameter if the method is non-static and the
  333.             // instruction is not newobj.
  334.             if (!(methodInfo is SymbolMethod) && methodInfo.IsStatic == false && !(opcode.Equals(OpCodes.Newobj)))
  335.                 stackchange--;
  336.             // Pop the optional parameters off the stack.
  337.             if (optionalParameterTypes != null)
  338.                 stackchange -= optionalParameterTypes.Length;
  339.             UpdateStackSize(opcode, stackchange);
  340.            
  341.             m_length = PutInteger4(tk, m_length, m_ILStream);
  342.         }
  343.        
  344.         public override void Emit(OpCode opcode, SignatureHelper signature)
  345.         {
  346.             int stackchange = 0;
  347.             if (signature == null)
  348.                 throw new ArgumentNullException("signature");
  349.            
  350.             EnsureCapacity(7);
  351.             InternalEmit(opcode);
  352.            
  353.             // The only IL instruction that has VarPop behaviour, that takes a
  354.             // Signature token as a parameter is calli. Pop the parameters and
  355.             // the native function pointer. To be conservative, do not pop the
  356.             // this pointer since this information is not easily derived from
  357.             // SignatureHelper.
  358.             if (opcode.m_pop == StackBehaviour.Varpop) {
  359.                 BCLDebug.Assert(opcode.Equals(OpCodes.Calli), "Unexpected opcode encountered for StackBehaviour VarPop.");
  360.                 // Pop the arguments..
  361.                 stackchange -= signature.ArgumentCount;
  362.                 // Pop native function pointer off the stack.
  363.                 stackchange--;
  364.                 UpdateStackSize(opcode, stackchange);
  365.             }
  366.            
  367.             int token = AddSignature(signature.GetSignature(true));
  368.             ;
  369.             m_length = PutInteger4(token, m_length, m_ILStream);
  370.         }
  371.        
  372.         //
  373.         //
  374.         // Exception related generation
  375.         //
  376.         //
  377.         public override Label BeginExceptionBlock()
  378.         {
  379.             return base.BeginExceptionBlock();
  380.         }
  381.        
  382.         public override void EndExceptionBlock()
  383.         {
  384.             base.EndExceptionBlock();
  385.         }
  386.        
  387.         public override void BeginExceptFilterBlock()
  388.         {
  389.             throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
  390.         }
  391.        
  392.         public override void BeginCatchBlock(Type exceptionType)
  393.         {
  394.             if (m_currExcStackCount == 0)
  395.                 throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
  396.            
  397.             __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1];
  398.            
  399.             if (current.GetCurrentState() == __ExceptionInfo.State_Filter) {
  400.                 if (exceptionType != null) {
  401.                     throw new ArgumentException(Environment.GetResourceString("Argument_ShouldNotSpecifyExceptionType"));
  402.                 }
  403.                
  404.                 this.Emit(OpCodes.Endfilter);
  405.             }
  406.             else {
  407.                 // execute this branch if previous clause is Catch or Fault
  408.                 if (exceptionType == null) {
  409.                     throw new ArgumentNullException("exceptionType");
  410.                 }
  411.                
  412.                 if (exceptionType.GetType() != typeof(RuntimeType))
  413.                     throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
  414.                
  415.                 Label endLabel = current.GetEndLabel();
  416.                 this.Emit(OpCodes.Leave, endLabel);
  417.                
  418.                 // if this is a catch block the exception will be pushed on the stack and we need to update the stack info
  419.                 UpdateStackSize(OpCodes.Nop, 1);
  420.             }
  421.            
  422.             current.MarkCatchAddr(m_length, exceptionType);
  423.            
  424.            
  425.             // this is relying on too much implementation details of the base and so it's highly breaking
  426.             // Need to have a more integreted story for exceptions
  427.             current.m_filterAddr[current.m_currentCatch - 1] = m_scope.GetTokenFor(exceptionType.TypeHandle);
  428.         }
  429.        
  430.         public override void BeginFaultBlock()
  431.         {
  432.             throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
  433.         }
  434.        
  435.         public override void BeginFinallyBlock()
  436.         {
  437.             base.BeginFinallyBlock();
  438.         }
  439.        
  440.         //
  441.         //
  442.         // debugger related calls.
  443.         //
  444.         //
  445.         public override void UsingNamespace(string ns)
  446.         {
  447.             throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
  448.         }
  449.        
  450.         public override void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn)
  451.         {
  452.             throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
  453.         }
  454.        
  455.         public override void BeginScope()
  456.         {
  457.             throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
  458.         }
  459.        
  460.         public override void EndScope()
  461.         {
  462.             throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
  463.         }
  464.        
  465.         //
  466.         // private implementation
  467.         //
  468.         internal override int GetMaxStackSize()
  469.         {
  470.             return m_maxStackSize;
  471.         }
  472.        
  473.         internal override int GetMemberRefToken(MethodBase methodInfo, Type[] optionalParameterTypes)
  474.         {
  475.             Type[] parameterTypes;
  476.            
  477.             if (optionalParameterTypes != null)
  478.                 if ((methodInfo.CallingConvention & CallingConventions.VarArgs) == 0)
  479.                
  480.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention"));
  481.            
  482.             if (!(methodInfo is RuntimeMethodInfo) && DynamicMethod.AsDynamicMethod(methodInfo) == null)
  483.                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "methodInfo");
  484.            
  485.             ParameterInfo[] paramInfo = methodInfo.GetParametersNoCopy();
  486.             if (paramInfo != null && paramInfo.Length != 0) {
  487.                 parameterTypes = new Type[paramInfo.Length];
  488.                 for (int i = 0; i < paramInfo.Length; i++) {
  489.                     parameterTypes[i] = paramInfo[i].ParameterType;
  490.                 }
  491.             }
  492.             else
  493.                 parameterTypes = null;
  494.            
  495.             SignatureHelper sig = GetMemberRefSignature(methodInfo.CallingConvention, methodInfo.GetReturnType(), parameterTypes, optionalParameterTypes);
  496.             return m_scope.GetTokenFor(new VarArgMethod(methodInfo as MethodInfo, sig));
  497.         }
  498.        
  499.         internal override SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
  500.         {
  501.             int cParams;
  502.             int i;
  503.             SignatureHelper sig;
  504.             if (parameterTypes == null)
  505.                 cParams = 0;
  506.             else
  507.                 cParams = parameterTypes.Length;
  508.             sig = SignatureHelper.GetMethodSigHelper(call, returnType);
  509.             for (i = 0; i < cParams; i++)
  510.                 sig.AddArgument(parameterTypes[i]);
  511.             if (optionalParameterTypes != null && optionalParameterTypes.Length != 0) {
  512.                 // add the sentinel
  513.                 sig.AddSentinel();
  514.                 for (i = 0; i < optionalParameterTypes.Length; i++)
  515.                     sig.AddArgument(optionalParameterTypes[i]);
  516.             }
  517.             return sig;
  518.         }
  519.        
  520.         private int AddStringLiteral(string s)
  521.         {
  522.             int token = m_scope.GetTokenFor(s);
  523.             return token | 1879048192;
  524.         }
  525.        
  526.         private int AddSignature(byte[] sig)
  527.         {
  528.             int token = m_scope.GetTokenFor(sig);
  529.             return token | 285212672;
  530.         }
  531.        
  532.     }
  533.    
  534.     internal class DynamicResolver : Resolver
  535.     {
  536.         #region Private Data Members
  537.         private __ExceptionInfo[] m_exceptions;
  538.         private byte[] m_exceptionHeader;
  539.         private DynamicMethod m_method;
  540.         private byte[] m_code;
  541.         private byte[] m_localSignature;
  542.         private int m_stackSize;
  543.         private DynamicScope m_scope;
  544.         #endregion
  545.        
  546.         #region Internal Methods
  547.         internal DynamicResolver(DynamicILGenerator ilGenerator)
  548.         {
  549.             m_stackSize = ilGenerator.GetMaxStackSize();
  550.             m_exceptions = ilGenerator.GetExceptions();
  551.             m_code = ilGenerator.BakeByteArray();
  552.             m_localSignature = ilGenerator.m_localSignature.InternalGetSignatureArray();
  553.             m_scope = ilGenerator.m_scope;
  554.            
  555.             m_method = (DynamicMethod)ilGenerator.m_methodBuilder;
  556.             m_method.m_resolver = this;
  557.         }
  558.        
  559.         internal DynamicResolver(DynamicILInfo dynamicILInfo)
  560.         {
  561.             m_stackSize = dynamicILInfo.MaxStackSize;
  562.             m_code = dynamicILInfo.Code;
  563.             m_localSignature = dynamicILInfo.LocalSignature;
  564.             m_exceptionHeader = dynamicILInfo.Exceptions;
  565.             //m_exceptions = dynamicILInfo.Exceptions;
  566.             m_scope = dynamicILInfo.DynamicScope;
  567.            
  568.             m_method = dynamicILInfo.DynamicMethod;
  569.             m_method.m_resolver = this;
  570.         }
  571.        
  572.         //
  573.         //
  574.         ~DynamicResolver()
  575.         {
  576.             DynamicMethod method = m_method;
  577.            
  578.             if (method == null)
  579.                 return;
  580.            
  581.             if (method.m_method.IsNullHandle())
  582.                 return;
  583.            
  584.             DestroyScout scout = null;
  585.             try {
  586.                 scout = new DestroyScout();
  587.             }
  588.             catch {
  589.                 // We go over all DynamicMethodDesc during AppDomain shutdown and make sure
  590.                 // that everything associated with them is released. So it is ok to skip reregistration
  591.                 // for finalization during appdomain shutdown
  592.                 if (!Environment.HasShutdownStarted && !AppDomain.CurrentDomain.IsFinalizingForUnload()) {
  593.                     // Try again later.
  594.                     GC.ReRegisterForFinalize(this);
  595.                 }
  596.                 return;
  597.             }
  598.            
  599.             // We can never ever have two active destroy scouts for the same method. We need to initialize the scout
  600.             // outside the try/reregister block to avoid possibility of reregistration for finalization with active scout.
  601.             scout.m_method = method.m_method;
  602.         }
  603.        
  604.         private class DestroyScout
  605.         {
  606.             internal RuntimeMethodHandle m_method;
  607.            
  608.             ~DestroyScout()
  609.             {
  610.                 if (m_method.IsNullHandle())
  611.                     return;
  612.                
  613.                 // It is not safe to destroy the method if the managed resolver is alive.
  614.                 if (m_method.GetResolver() != null) {
  615.                     if (!Environment.HasShutdownStarted && !AppDomain.CurrentDomain.IsFinalizingForUnload()) {
  616.                         // Somebody might have been holding a reference on us via weak handle.
  617.                         // We will keep trying. It will be hopefully released eventually.
  618.                         GC.ReRegisterForFinalize(this);
  619.                     }
  620.                     return;
  621.                 }
  622.                
  623.                 m_method.Destroy();
  624.             }
  625.         }
  626.        
  627.         // Keep in sync with vm/dynamicmethod.h
  628.         internal enum SecurityControlFlags
  629.         {
  630.             SkipVisibilityChecks = 1
  631.         }
  632.        
  633.         internal override void GetJitContext(ref int securityControlFlags, ref RuntimeTypeHandle typeOwner)
  634.         {
  635.             securityControlFlags = (m_method.m_skipVisibility) ? (int)SecurityControlFlags.SkipVisibilityChecks : 0;
  636.             typeOwner = (m_method.m_typeOwner != null) ? m_method.m_typeOwner.TypeHandle : RuntimeTypeHandle.EmptyHandle;
  637.         }
  638.        
  639.         internal override byte[] GetCodeInfo(ref int stackSize, ref int initLocals, ref int EHCount)
  640.         {
  641.             stackSize = m_stackSize;
  642.             if (m_exceptionHeader != null && m_exceptionHeader.Length != 0) {
  643.                 if (m_exceptionHeader.Length < 4)
  644.                     throw new FormatException();
  645.                
  646.                 byte header = m_exceptionHeader[0];
  647.                
  648.                 // Fat
  649.                 if ((header & 64) != 0) {
  650.                     byte[] size = new byte[4];
  651.                     for (int q = 0; q < 3; q++)
  652.                         size[q] = m_exceptionHeader[q + 1];
  653.                     EHCount = (BitConverter.ToInt32(size, 0) - 4) / 24;
  654.                 }
  655.                 else
  656.                     EHCount = (m_exceptionHeader[1] - 2) / 12;
  657.             }
  658.             else {
  659.                 EHCount = ILGenerator.CalculateNumberOfExceptions(m_exceptions);
  660.             }
  661.             initLocals = (m_method.InitLocals) ? 1 : 0;
  662.             return m_code;
  663.         }
  664.        
  665.         internal override byte[] GetLocalsSignature()
  666.         {
  667.             return m_localSignature;
  668.         }
  669.        
  670.         unsafe internal override byte[] GetRawEHInfo()
  671.         {
  672.             return m_exceptionHeader;
  673.         }
  674.        
  675.         unsafe internal override void GetEHInfo(int excNumber, void* exc)
  676.         {
  677.             CORINFO_EH_CLAUSE* exception = (CORINFO_EH_CLAUSE*)exc;
  678.             for (int i = 0; i < m_exceptions.Length; i++) {
  679.                 int excCount = m_exceptions[i].GetNumberOfCatches();
  680.                 if (excNumber < excCount) {
  681.                     // found the right exception block
  682.                     exception->Flags = m_exceptions[i].GetExceptionTypes()[excNumber];
  683.                     exception->Flags |= Resolver.COR_ILEXCEPTION_CLAUSE_MUST_CACHE_CLASS;
  684.                     exception->TryOffset = m_exceptions[i].GetStartAddress();
  685.                     if ((exception->Flags & __ExceptionInfo.Finally) != __ExceptionInfo.Finally)
  686.                         exception->TryLength = m_exceptions[i].GetEndAddress() - exception->TryOffset;
  687.                     else
  688.                         exception->TryLength = m_exceptions[i].GetFinallyEndAddress() - exception->TryOffset;
  689.                     exception->HandlerOffset = m_exceptions[i].GetCatchAddresses()[excNumber];
  690.                     exception->HandlerLength = m_exceptions[i].GetCatchEndAddresses()[excNumber] - exception->HandlerOffset;
  691.                     // this is cheating because the filter address is the token of the class only for light code gen
  692.                     exception->ClassTokenOrFilterOffset = m_exceptions[i].GetFilterAddresses()[excNumber];
  693.                     break;
  694.                 }
  695.                 excNumber -= excCount;
  696.             }
  697.         }
  698.        
  699.         internal override string GetStringLiteral(int token)
  700.         {
  701.             return m_scope.GetString(token);
  702.         }
  703.        
  704.         internal override int IsValidToken(int token)
  705.         {
  706.             return (m_scope[token] != null) ? 1 : 0;
  707.         }
  708.        
  709.         unsafe internal override void* GetInstantiationInfo(int token)
  710.         {
  711.             GenericMethodInfo gmi = m_scope[token] as GenericMethodInfo;
  712.             if (gmi != null) {
  713.                 return (void*)gmi.m_context.Value;
  714.             }
  715.             return null;
  716.         }
  717.        
  718.         unsafe internal override void* ResolveToken(int token)
  719.         {
  720.             object handle = m_scope[token];
  721.            
  722.             if (handle is RuntimeTypeHandle) {
  723.                 RuntimeTypeHandle typeHandle = (RuntimeTypeHandle)handle;
  724.                 return (void*)typeHandle.Value;
  725.             }
  726.             else if (handle is RuntimeMethodHandle) {
  727.                 RuntimeMethodHandle methodHandle = (RuntimeMethodHandle)handle;
  728.                 return (void*)methodHandle.Value;
  729.             }
  730.             else if (handle is RuntimeFieldHandle) {
  731.                 RuntimeFieldHandle fieldHandle = (RuntimeFieldHandle)handle;
  732.                 return (void*)fieldHandle.Value;
  733.             }
  734.             else if (handle is DynamicMethod) {
  735.                 DynamicMethod dynMeth = (DynamicMethod)handle;
  736.                 RuntimeMethodHandle methodHandle = dynMeth.GetMethodDescriptor();
  737.                 return (void*)methodHandle.Value;
  738.             }
  739.             else if (handle is GenericMethodInfo) {
  740.                 GenericMethodInfo gmi = (GenericMethodInfo)handle;
  741.                 return (void*)gmi.m_method.Value;
  742.             }
  743.             else if (handle is VarArgMethod) {
  744.                 VarArgMethod vaMeth = (VarArgMethod)handle;
  745.                 DynamicMethod dm = vaMeth.m_method as DynamicMethod;
  746.                 if (dm == null)
  747.                     return (void*)vaMeth.m_method.MethodHandle.Value;
  748.                 else
  749.                     return (void*)dm.GetMethodDescriptor().Value;
  750.             }
  751.            
  752.             return null;
  753.         }
  754.        
  755.         internal override byte[] ResolveSignature(int token, int fromMethod)
  756.         {
  757.             return m_scope.ResolveSignature(token, fromMethod);
  758.         }
  759.        
  760.         unsafe internal override int ParentToken(int token)
  761.         {
  762.             RuntimeTypeHandle owner = RuntimeTypeHandle.EmptyHandle;
  763.            
  764.             object handle = m_scope[token];
  765.            
  766.             if (handle is RuntimeMethodHandle) {
  767.                 RuntimeMethodHandle method = (RuntimeMethodHandle)handle;
  768.                 owner = method.GetDeclaringType();
  769.             }
  770.             else if (handle is RuntimeFieldHandle) {
  771.                 RuntimeFieldHandle field = (RuntimeFieldHandle)handle;
  772.                 owner = field.GetApproxDeclaringType();
  773.             }
  774.             else if (handle is DynamicMethod) {
  775.                 DynamicMethod dynMeth = (DynamicMethod)handle;
  776.                 owner = dynMeth.m_method.GetDeclaringType();
  777.             }
  778.             else if (handle is GenericMethodInfo) {
  779.                 GenericMethodInfo gmi = (GenericMethodInfo)handle;
  780.                 owner = gmi.m_context;
  781.             }
  782.             else if (handle is VarArgMethod) {
  783.                 VarArgMethod varargMeth = (VarArgMethod)handle;
  784.                 if (varargMeth.m_method is DynamicMethod)
  785.                     owner = ((DynamicMethod)varargMeth.m_method).m_method.GetDeclaringType();
  786.                 else if (varargMeth.m_method is DynamicMethod.RTDynamicMethod)
  787.                     owner = ((DynamicMethod.RTDynamicMethod)varargMeth.m_method).m_owner.m_method.GetDeclaringType();
  788.                 else
  789.                     owner = varargMeth.m_method.MethodHandle.GetDeclaringType();
  790.             }
  791.            
  792.             if (owner.IsNullHandle())
  793.                 return -1;
  794.            
  795.             return m_scope.GetTokenFor(owner);
  796.         }
  797.        
  798.         internal override MethodInfo GetDynamicMethod()
  799.         {
  800.             return m_method.GetMethodInfo();
  801.         }
  802.         #endregion
  803.     }
  804.    
  805.     [System.Runtime.InteropServices.ComVisible(true)]
  806.     public class DynamicILInfo
  807.     {
  808.         #region Private Data Members
  809.         private DynamicMethod m_method;
  810.         private DynamicScope m_scope;
  811.         private byte[] m_exceptions;
  812.         private byte[] m_code;
  813.         private byte[] m_localSignature;
  814.         private int m_maxStackSize;
  815.         private int m_methodSignature;
  816.         #endregion
  817.        
  818.         #region Constructor
  819.         internal DynamicILInfo(DynamicScope scope, DynamicMethod method, byte[] methodSignature)
  820.         {
  821.             m_method = method;
  822.             m_scope = scope;
  823.             m_methodSignature = m_scope.GetTokenFor(methodSignature);
  824.             m_exceptions = new byte[0];
  825.             m_code = new byte[0];
  826.             m_localSignature = new byte[0];
  827.         }
  828.         #endregion
  829.        
  830.         #region Internal Methods
  831.         unsafe internal RuntimeMethodHandle GetCallableMethod(void* module)
  832.         {
  833.             return new RuntimeMethodHandle(ModuleHandle.GetDynamicMethod(module, m_method.Name, (byte[])m_scope[m_methodSignature], new DynamicResolver(this)));
  834.         }
  835.         internal byte[] LocalSignature {
  836.             get {
  837.                 if (m_localSignature == null)
  838.                     m_localSignature = SignatureHelper.GetLocalVarSigHelper().InternalGetSignatureArray();
  839.                
  840.                 return m_localSignature;
  841.             }
  842.         }
  843.         internal byte[] Exceptions {
  844.             get { return m_exceptions; }
  845.         }
  846.         internal byte[] Code {
  847.             get { return m_code; }
  848.         }
  849.         internal int MaxStackSize {
  850.             get { return m_maxStackSize; }
  851.         }
  852.         #endregion
  853.        
  854.         #region Public ILGenerator Methods
  855.         public DynamicMethod DynamicMethod {
  856.             get { return m_method; }
  857.         }
  858.         internal DynamicScope DynamicScope {
  859.             get { return m_scope; }
  860.         }
  861.        
  862.         public void SetCode(byte[] code, int maxStackSize)
  863.         {
  864.             if (code == null)
  865.                 code = new byte[0];
  866.            
  867.             m_code = (byte[])code.Clone();
  868.             m_maxStackSize = maxStackSize;
  869.         }
  870.        
  871.         [CLSCompliant(false)]
  872.         unsafe public void SetCode(byte* code, int codeSize, int maxStackSize)
  873.         {
  874.             if (codeSize < 0)
  875.                 throw new ArgumentOutOfRangeException("codeSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
  876.            
  877.             m_code = new byte[codeSize];
  878.             for (int i = 0; i < codeSize; i++) {
  879.                 m_code[i] = *code;
  880.                 code++;
  881.             }
  882.            
  883.             m_maxStackSize = maxStackSize;
  884.         }
  885.        
  886.         public void SetExceptions(byte[] exceptions)
  887.         {
  888.             if (exceptions == null)
  889.                 exceptions = new byte[0];
  890.            
  891.             m_exceptions = (byte[])exceptions.Clone();
  892.         }
  893.        
  894.         [CLSCompliant(false)]
  895.         unsafe public void SetExceptions(byte* exceptions, int exceptionsSize)
  896.         {
  897.             if (exceptionsSize < 0)
  898.                 throw new ArgumentOutOfRangeException("exceptionsSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
  899.            
  900.             m_exceptions = new byte[exceptionsSize];
  901.            
  902.             for (int i = 0; i < exceptionsSize; i++) {
  903.                 m_exceptions[i] = *exceptions;
  904.                 exceptions++;
  905.             }
  906.         }
  907.        
  908.         public void SetLocalSignature(byte[] localSignature)
  909.         {
  910.             if (localSignature == null)
  911.                 localSignature = new byte[0];
  912.            
  913.             m_localSignature = (byte[])localSignature.Clone();
  914.         }
  915.        
  916.         [CLSCompliant(false)]
  917.         unsafe public void SetLocalSignature(byte* localSignature, int signatureSize)
  918.         {
  919.             if (signatureSize < 0)
  920.                 throw new ArgumentOutOfRangeException("signatureSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
  921.            
  922.             m_localSignature = new byte[signatureSize];
  923.             for (int i = 0; i < signatureSize; i++) {
  924.                 m_localSignature[i] = *localSignature;
  925.                 localSignature++;
  926.             }
  927.         }
  928.         #endregion
  929.        
  930.         #region Public Scope Methods
  931.         public int GetTokenFor(RuntimeMethodHandle method)
  932.         {
  933.             return DynamicScope.GetTokenFor(method);
  934.         }
  935.         public int GetTokenFor(DynamicMethod method)
  936.         {
  937.             return DynamicScope.GetTokenFor(method);
  938.         }
  939.         public int GetTokenFor(RuntimeMethodHandle method, RuntimeTypeHandle contextType)
  940.         {
  941.             return DynamicScope.GetTokenFor(method, contextType);
  942.         }
  943.         public int GetTokenFor(RuntimeFieldHandle field)
  944.         {
  945.             return DynamicScope.GetTokenFor(field);
  946.         }
  947.         public int GetTokenFor(RuntimeTypeHandle type)
  948.         {
  949.             return DynamicScope.GetTokenFor(type);
  950.         }
  951.         public int GetTokenFor(string literal)
  952.         {
  953.             return DynamicScope.GetTokenFor(literal);
  954.         }
  955.         public int GetTokenFor(byte[] signature)
  956.         {
  957.             return DynamicScope.GetTokenFor(signature);
  958.         }
  959.         #endregion
  960.     }
  961.    
  962.     internal class DynamicScope
  963.     {
  964.         #region Private Data Members
  965.         internal ArrayList m_tokens;
  966.         #endregion
  967.        
  968.         #region Constructor
  969.         unsafe internal DynamicScope()
  970.         {
  971.             m_tokens = new ArrayList();
  972.             m_tokens.Add(null);
  973.         }
  974.         #endregion
  975.        
  976.         #region Internal Methods
  977.         internal object this[int token]
  978.         {
  979.             get {
  980.                 token &= 16777215;
  981.                
  982.                 if (token < 0 || token > m_tokens.Count)
  983.                     return null;
  984.                
  985.                 return m_tokens[token];
  986.             }
  987.         }
  988.        
  989.         internal int GetTokenFor(VarArgMethod varArgMethod)
  990.         {
  991.             return m_tokens.Add(varArgMethod) | (int)MetadataTokenType.MemberRef;
  992.         }
  993.         internal string GetString(int token)
  994.         {
  995.             return this[token] as string;
  996.         }
  997.        
  998.         internal byte[] ResolveSignature(int token, int fromMethod)
  999.         {
  1000.             if (fromMethod == 0)
  1001.                 return (byte[])this[token];
  1002.            
  1003.             VarArgMethod vaMethod = this[token] as VarArgMethod;
  1004.            
  1005.             if (vaMethod == null)
  1006.                 return null;
  1007.            
  1008.             return vaMethod.m_signature.GetSignature(true);
  1009.         }
  1010.         #endregion
  1011.        
  1012.         #region Public Methods
  1013.         public int GetTokenFor(RuntimeMethodHandle method)
  1014.         {
  1015.             MethodBase m = RuntimeType.GetMethodBase(method);
  1016.            
  1017.             if (m.DeclaringType != null && m.DeclaringType.IsGenericType)
  1018.                 throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_MethodDeclaringTypeGenericLcg"), m, m.DeclaringType.GetGenericTypeDefinition()));
  1019.            
  1020.             return m_tokens.Add(method) | (int)MetadataTokenType.MethodDef;
  1021.         }
  1022.         public int GetTokenFor(RuntimeMethodHandle method, RuntimeTypeHandle typeContext)
  1023.         {
  1024.             return m_tokens.Add(new GenericMethodInfo(method, typeContext)) | (int)MetadataTokenType.MethodDef;
  1025.         }
  1026.         public int GetTokenFor(DynamicMethod method)
  1027.         {
  1028.             return m_tokens.Add(method) | (int)MetadataTokenType.MethodDef;
  1029.         }
  1030.         public int GetTokenFor(RuntimeFieldHandle field)
  1031.         {
  1032.             return m_tokens.Add(field) | (int)MetadataTokenType.FieldDef;
  1033.         }
  1034.         public int GetTokenFor(RuntimeTypeHandle type)
  1035.         {
  1036.             return m_tokens.Add(type) | (int)MetadataTokenType.TypeDef;
  1037.         }
  1038.         public int GetTokenFor(string literal)
  1039.         {
  1040.             return m_tokens.Add(literal) | (int)MetadataTokenType.String;
  1041.         }
  1042.         public int GetTokenFor(byte[] signature)
  1043.         {
  1044.             return m_tokens.Add(signature) | (int)MetadataTokenType.Signature;
  1045.         }
  1046.         #endregion
  1047.     }
  1048.    
  1049.     internal class GenericMethodInfo
  1050.     {
  1051.         internal RuntimeMethodHandle m_method;
  1052.         internal RuntimeTypeHandle m_context;
  1053.        
  1054.         internal GenericMethodInfo(RuntimeMethodHandle method, RuntimeTypeHandle context)
  1055.         {
  1056.             m_method = method;
  1057.             m_context = context;
  1058.         }
  1059.     }
  1060.    
  1061.     internal class VarArgMethod
  1062.     {
  1063.         internal MethodInfo m_method;
  1064.         internal SignatureHelper m_signature;
  1065.        
  1066.         internal VarArgMethod(MethodInfo method, SignatureHelper signature)
  1067.         {
  1068.             m_method = method;
  1069.             m_signature = signature;
  1070.         }
  1071.     }
  1072.    
  1073. }

Developer Fusion