예제 #1
0
        private ITest BuildCalli()
        {
            var action        = Build();
            var typeBuilder   = Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class | TypeAttributes.Public);
            var pointerField  = typeBuilder.DefineField("pointer", typeof(IntPtr), FieldAttributes.Private | FieldAttributes.InitOnly);
            var delegateField = typeBuilder.DefineField("delegate", typeof(Delegate), FieldAttributes.Private | FieldAttributes.InitOnly);
            var constructor   = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(IntPtr), typeof(Delegate) });
            var il            = new GroboIL(constructor);

            il.Ldarg(0);
            il.Ldarg(1);
            il.Stfld(pointerField);
            il.Ldarg(0);
            il.Ldarg(2);
            il.Stfld(delegateField);
            il.Ret();
            var method = typeBuilder.DefineMethod("DoNothing", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes);

            il = new GroboIL(method);
            il.Ldarg(0);
            il.Ldfld(pointerField);
            il.Calli(CallingConventions.Standard, typeof(void), Type.EmptyTypes);
            il.Ret();
            typeBuilder.DefineMethodOverride(method, typeof(ITest).GetMethod("DoNothing"));
            typeBuilder.AddInterfaceImplementation(typeof(ITest));
            var type = typeBuilder.CreateType();

            return((ITest)Activator.CreateInstance(type, new object[] { DynamicMethodInvokerBuilder.DynamicMethodPointerExtractor((DynamicMethod)action.Item2), action.Item1 }));
        }
예제 #2
0
        private SizeCounterDelegate BuildCounter(Type type, bool ignoreCustomSerialization)
        {
            IntPtr counter = GetCounter(type, ignoreCustomSerialization);

            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(object), typeof(bool), typeof(WriterContext) }, GetType(), true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldarg(0); // stack: [obj]
                if (type.IsValueType)
                {
                    il.Unbox_Any(type); // stack: [(type)obj]
                }
                else
                {
                    il.Castclass(type);                                                                                  // stack: [(type)obj]
                }
                il.Ldarg(1);                                                                                             // stack: [(type)obj, writeEmpty]
                il.Ldarg(2);                                                                                             // stack: [(type)obj, writeEmpty, context]
                il.Ldc_IntPtr(counter);                                                                                  // stack: [(type)obj, writeEmpty, context, counter]
                il.Calli(CallingConventions.Standard, typeof(int), new[] { type, typeof(bool), typeof(WriterContext) }); // counter((type)obj, writeEmpty, context); stack: []
                il.Ret();
            }

            return((SizeCounterDelegate)dynamicMethod.CreateDelegate(typeof(SizeCounterDelegate)));
        }
예제 #3
0
        private WriterDelegate BuildWriter(Type type, bool ignoreCustomSerialization)
        {
            IntPtr writer = GetWriter(type, ignoreCustomSerialization);

            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), new[] { typeof(object), typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }, module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldarg(0); // stack: [obj]
                if (type.IsValueType)
                {
                    il.Unbox_Any(type); // stack: [(type)obj]
                }
                else
                {
                    il.Castclass(type);                                                                                                                                // stack: [(type)obj]
                }
                il.Ldarg(1);                                                                                                                                           // stack: [(type)obj, writeEmpty]
                il.Ldarg(2);                                                                                                                                           // stack: [(type)obj, writeEmpty, result]
                il.Ldarg(3);                                                                                                                                           // stack: [(type)obj, writeEmpty, result, ref index]
                il.Ldarg(4);                                                                                                                                           // stack: [(type)obj, writeEmpty, result, ref index, context]
                il.Ldc_IntPtr(writer);
                il.Calli(CallingConventions.Standard, typeof(void), new[] { type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }); // writer.write<T>((type)obj, writeEmpty, result, ref index, context); stack: []
                il.Ret();
            }

            return((WriterDelegate)dynamicMethod.CreateDelegate(typeof(WriterDelegate)));
        }
예제 #4
0
파일: Test.cs 프로젝트: qinfengzhu/gremit
 private static void BuildIlWithNativeCallingConvention(MethodBuilder methodBuilder)
 {
     using (var il = new GroboIL(methodBuilder))
     {
         il.Ldc_I4(10);
         il.Ldarg(0);
         il.Calli(CallingConvention.StdCall, typeof(int), new[] { typeof(int) });
         il.Ret();
     }
 }
        public void CallWriter(GroboIL il, Type type)
        {
            var counter = Context.GetWriter(type);

            if (counter.Pointer != IntPtr.Zero)
            {
                il.Ldc_IntPtr(counter.Pointer);
            }
            else
            {
                il.Ldfld(Context.ConstantsType.GetField("pointers", BindingFlags.Static | BindingFlags.NonPublic));
                il.Ldc_I4(counter.Index);
                il.Ldelem(typeof(IntPtr));
            }
            il.Calli(CallingConventions.Standard, typeof(void), new[] { type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) });
        }
예제 #6
0
        private SizeCounterDelegate <T> BuildCounter <T>(bool ignoreCustomSerialization)
        {
            var    type    = typeof(T);
            IntPtr counter = GetCounter(type, ignoreCustomSerialization);

            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { type, typeof(bool), typeof(WriterContext) }, GetType(), true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldarg(0);                                                                                             // stack: [obj]
                il.Ldarg(1);                                                                                             // stack: [obj, writeEmpty]
                il.Ldarg(2);                                                                                             // stack: [obj, writeEmpty, context]
                il.Ldc_IntPtr(counter);                                                                                  // stack: [obj, writeEmpty, context, counter]
                il.Calli(CallingConventions.Standard, typeof(int), new[] { type, typeof(bool), typeof(WriterContext) }); // counter(obj, writeEmpty, context); stack: []
                il.Ret();
            }
            return((SizeCounterDelegate <T>)dynamicMethod.CreateDelegate(typeof(SizeCounterDelegate <T>)));
        }
 public static void CallReader(GroboIL il, Type type, ReaderTypeBuilderContext context)
 {
     LoadReader(il, type, context);
     il.Calli(CallingConventions.Standard, typeof(void), new[] { typeof(IntPtr), typeof(int).MakeByRefType(), type.MakeByRefType(), typeof(ReaderContext) });
 }
예제 #8
0
        private Type BuildReaderInvoker()
        {
            var argument     = Type.GetGenericArguments()[0];
            var typeBuilder  = module.DefineType("ReaderInvoker_" + Type, TypeAttributes.Public | TypeAttributes.Class);
            var reader       = typeBuilder.DefineField("reader", typeof(IntPtr), FieldAttributes.Private);
            var serializerId = typeBuilder.DefineField("serializerId", typeof(long), FieldAttributes.Private);
            var constructor  = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(IntPtr), typeof(long) });

            using (var il = new GroboIL(constructor))
            {
                il.Ldarg(0);            // stack: [this]
                il.Ldarg(1);            // stack: [this, reader]
                il.Stfld(reader);       // this.reader = reader; stack: []
                il.Ldarg(0);            // stack: [this]
                il.Ldarg(2);            // stack: [this, serializerId]
                il.Stfld(serializerId); // this.serializerId = serializerId; stack: []
                il.Ret();
            }
            var method = typeBuilder.DefineMethod("Read", MethodAttributes.Public, argument, new[] { typeof(byte[]) });

            using (var il = new GroboIL(method))
            {
                var pinnedData = il.DeclareLocal(typeof(byte).MakeByRefType(), "pinnedData", true);
                il.Ldarg(1);                                                                                                    // stack: [data]
                il.Ldc_I4(0);                                                                                                   // stack: [data, 0]
                il.Ldelema(typeof(byte));                                                                                       // stack: [&data[0]]
                il.Stloc(pinnedData);                                                                                           // pinnedData = &data[0]; stack: []
                var index = il.DeclareLocal(typeof(int), "index");
                il.Ldc_I4(0);                                                                                                   // stack: [0]
                il.Stloc(index);                                                                                                // index = 0; stack: []
                var context = il.DeclareLocal(typeof(ReaderContext), "context");
                il.Ldarg(0);                                                                                                    // stack: [this]
                il.Ldfld(serializerId);                                                                                         // stack: [this.serializerId]
                il.Ldarg(1);                                                                                                    // stack: [this.serializerId, data]
                il.Ldlen();                                                                                                     // stack: [this.serializerId, data.Length]
                il.Ldc_I4(0);                                                                                                   // stack: [this.serializerId, data.Length, 0]
                il.Ldc_I4(0);                                                                                                   // stack: [this.serializerId, data.Length, 0, 0]
                il.Newobj(typeof(ReaderContext).GetConstructor(new[] { typeof(long), typeof(int), typeof(int), typeof(int) })); // stack: [new ReaderContext(this.serializerId, data.Length, 0, 0)]
                il.Stloc(context);                                                                                              // context = new ReaderContext(..); stack: []

                var result = il.DeclareLocal(argument, "result");
                il.Ldloc(pinnedData);                                                // stack: [data]
                il.Conv <IntPtr>();                                                  // stack: [(IntPtr)data]
                il.Ldloca(index);                                                    // stack: [(IntPtr)data, ref index]
                il.Ldloca(result);                                                   // stack: [(IntPtr)data, ref index, ref result]
                il.Ldloc(context);                                                   // stack: [(IntPtr)data, ref index, ref result, context]
                il.Ldarg(0);                                                         // stack: [(IntPtr)data, ref index, ref result, context, this]
                il.Ldfld(reader);                                                    // stack: [(IntPtr)data, ref index, ref result, context, this.reader]
                var parameterTypes = new[] { typeof(IntPtr), typeof(int).MakeByRefType(), argument.MakeByRefType(), typeof(ReaderContext) };
                il.Calli(CallingConventions.Standard, typeof(void), parameterTypes); // this.reader((IntPtr)data, ref index, ref result, context); stack: []
                il.FreePinnedLocal(pinnedData);                                      // pinnedData = null; stack: []
                var retLabel = il.DefineLabel("ret");
                il.Ldarg(1);                                                         // stack: [data]
                il.Ldlen();                                                          // stack: [data.Length]
                il.Ldloc(index);                                                     // stack: [data.Length, index]
                il.Beq(retLabel);                                                    // if(data.Length == index) goto ret; stack: []
                il.Ldstr("Encountered extra data");
                il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                il.Throw();

                il.MarkLabel(retLabel);
                il.Ldloc(result);
                il.Ret();
            }
            return(typeBuilder.CreateType());
        }