private ITest BuildCall()
        {
            var typeBuilder     = Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class | TypeAttributes.Public);
            var doNothingMethod = typeBuilder.DefineMethod("DoNothingImpl", MethodAttributes.Public, typeof(void), Type.EmptyTypes);

            using (var il = new GroboIL(doNothingMethod))
            {
                il.Ldfld(xField);
                il.Ldc_I4(1);
                il.Add();
                il.Stfld(xField);
                il.Ret();
            }
            var method = typeBuilder.DefineMethod("DoNothing", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                il.Call(doNothingMethod);
                il.Ret();
            }
            typeBuilder.DefineMethodOverride(method, typeof(ITest).GetMethod("DoNothing"));
            typeBuilder.AddInterfaceImplementation(typeof(ITest));
            var type = typeBuilder.CreateType();

            return((ITest)Activator.CreateInstance(type));
        }
        private ITest BuildDelegate()
        {
            var action      = Build();
            var typeBuilder = Module.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Class | TypeAttributes.Public);
            var actionField = typeBuilder.DefineField("action", typeof(Action), FieldAttributes.Private | FieldAttributes.InitOnly);
            var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(Action) });

            using (var il = new GroboIL(constructor))
            {
                il.Ldarg(0);
                il.Ldarg(1);
                il.Stfld(actionField);
                il.Ret();
            }
            var method = typeBuilder.DefineMethod("DoNothing", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), Type.EmptyTypes);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                il.Ldfld(actionField);
                il.Call(typeof(Action).GetMethod("Invoke", Type.EmptyTypes), typeof(Action));
                il.Ret();
            }
            typeBuilder.DefineMethodOverride(method, typeof(ITest).GetMethod("DoNothing"));
            typeBuilder.AddInterfaceImplementation(typeof(ITest));
            var type = typeBuilder.CreateType();

            return((ITest)Activator.CreateInstance(type, new object[] { action.Item1 }));
        }
Esempio n. 3
0
 private void LoadTupleField(GroboIL il, ValueTupleField tupleFiled)
 {
     il.Ldstr(tupleFiled.NameInUserCode);
     il.Ldarga(0);
     il.Ldfld(tupleFiled.FieldInfo);
     if (tupleFiled.FieldInfo.FieldType.IsValueType)
     {
         il.Box(tupleFiled.FieldInfo.FieldType);
     }
 }
Esempio n. 4
0
        private Func <string, string> BuildSwitch4()
        {
            Init(new[] { "0", "2", "5", "1000001", "7", "1000000" });
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(string), new[] { typeof(string) }, Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                var zzzLabel = il.DefineLabel("zzz");
                var qxxLabel = il.DefineLabel("qxx");
                var qzzLabel = il.DefineLabel("qzz");
                var xxxLabel = il.DefineLabel("xxx");
                var index    = il.DeclareLocal(typeof(uint));
                il.Ldfld(typeof(TestPerformance).GetField("testValues2"));
                il.Ldarg(0);
                il.Call(typeof(object).GetMethod("GetHashCode"), typeof(string));
                il.Ldc_I4(testValues2.Length);
                il.Rem(true);
                il.Stloc(index);
                il.Ldloc(index);
                il.Ldelem(typeof(string));
                il.Ldarg(0);
                il.Call(typeof(object).GetMethod("Equals", new[] { typeof(object) }), typeof(string));
                il.Brfalse(xxxLabel);
                il.Ldfld(typeof(TestPerformance).GetField("indexes2"));
                il.Ldloc(index);
                il.Ldelem(typeof(int));
                il.Switch(zzzLabel, zzzLabel, qxxLabel, qxxLabel, qzzLabel, qzzLabel);
                il.Br(xxxLabel);
                il.MarkLabel(zzzLabel);
                il.Ldstr("zzz");
                il.Ret();
                il.MarkLabel(qxxLabel);
                il.Ldstr("qxx");
                il.Ret();
                il.MarkLabel(qzzLabel);
                il.Ldstr("qzz");
                il.Ret();
                il.MarkLabel(xxxLabel);
                il.Ldstr("xxx");
                il.Ret();
            }
            return((Func <string, string>)dynamicMethod.CreateDelegate(typeof(Func <string, string>)));
        }
Esempio n. 5
0
        public static TryGetValueDelegate <T> Build <T>(string[] keys, T[] values, Func <string, int> hashCodeEvaluator)
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool),
                                           new[] { typeof(Closure <T>), typeof(string), typeof(T).MakeByRefType() }, typeof(string), true);
            var hashCodes = keys.Select(hashCodeEvaluator).ToArray();
            int n         = keys.Length;
            var indexes   = new int[n];

            for (int i = 0; i < n; ++i)
            {
                indexes[i] = i;
            }
            Array.Sort(indexes, (lhs, rhs) => hashCodes[lhs].CompareTo(hashCodes[rhs]));
            using (var il = new GroboIL(method))
            {
                var retFalseLabel = il.DefineLabel("retFalse");
                var hashCode      = il.DeclareLocal(typeof(int), "hashCode");
                il.Ldarg(0);                                                                                          // stack: [closure]
                il.Ldfld(HackHelpers.GetField <Closure <T> >(x => x.hashCodeEvaluator));                              // stack: [closure.hashCodeEvaluator]
                il.Ldarg(1);                                                                                          // stack: [closure.hashCodeEvaluator, key]
                il.Call(typeof(Func <string, int>).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public)); // stack: [closure.hashCodeEvaluator(key)]
                il.Stloc(hashCode);                                                                                   // hashCode = closure.hashCodeEvaluator(key); stack: []

                var context = new EmittingContext
                {
                    Il            = il,
                    Keys          = keys,
                    HashCodes     = hashCodes,
                    Indexes       = indexes,
                    HashCode      = hashCode,
                    RetFalseLabel = retFalseLabel
                };
                DoBinarySearch <T>(context, 0, n - 1);
                il.MarkLabel(retFalseLabel);
                il.Ldarg(2); // stack: [ref value]
                if (typeof(T).IsValueType)
                {
                    il.Initobj(typeof(T)); // value = default(T); stack: []
                }
                else
                {
                    il.Ldnull();         // stack: [ref value, null]
                    il.Stind(typeof(T)); // value = null; stack: []
                }
                il.Ldc_I4(0);            // stack: [false]
                il.Ret();
            }
            var closure = new Closure <T>
            {
                hashCodeEvaluator = hashCodeEvaluator,
                values            = values
            };

            return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), closure));
        }
        private static Tuple <Delegate, IntPtr> EmitFieldExtractor <T, TValue>(FieldInfo field)
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(TValue), new[] { typeof(T) }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0); // stack: [list]
                il.Ldfld(field);
                il.Ret();
            }
            return(new Tuple <Delegate, IntPtr>((Func <T, TValue>)method.CreateDelegate(typeof(Func <T, TValue>)), DynamicMethodInvokerBuilder.DynamicMethodPointerExtractor(method)));
        }
Esempio n. 7
0
        private DynamicMethod BuildAccessorMethod()
        {
            var assertMethod = typeof(TestGrobufUsages).GetMethod("AssertDateTimeOffsetFields", BindingFlags.Static | BindingFlags.NonPublic);

            var method = new DynamicMethod("Grobuf_Write_DateTimeOffset_" + Guid.NewGuid(), typeof(void), new[] { dateTimeOffsetType }, typeof(TestGrobufUsages), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarga(0);                                                          // stack: [obj]
                il.Ldfld(GetDateTimeOffsetField("_dateTime", "m_dateTime"));           // stack: [obj.m_dateTime]

                il.Ldarga(0);                                                          // stack: [obj]
                il.Ldfld(GetDateTimeOffsetField("_offsetMinutes", "m_offsetMinutes")); // stack: [obj.m_offsetMinutes]

                il.Call(assertMethod);                                                 // stack: []

                il.Ret();
            }

            return(method);
        }
Esempio n. 8
0
        private Func <int, string> BuildSwitch2()
        {
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(string), new[] { typeof(int) }, Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                var zzzLabel = il.DefineLabel("zzz");
                var qxxLabel = il.DefineLabel("qxx");
                var qzzLabel = il.DefineLabel("qzz");
                var xxxLabel = il.DefineLabel("xxx");
                var index    = il.DeclareLocal(typeof(uint));
                il.Ldfld(typeof(TestPerformance).GetField("testValues"));
                il.Ldarg(0);
                il.Ldc_I4(14);
                il.Rem(true);
                il.Stloc(index);
                il.Ldloc(index);
                il.Ldelem(typeof(int));
                il.Ldarg(0);
                il.Bne_Un(xxxLabel);
                il.Ldfld(typeof(TestPerformance).GetField("indexes"));
                il.Ldloc(index);
                il.Ldelem(typeof(int));
                il.Switch(zzzLabel, zzzLabel, qxxLabel, qzzLabel, qzzLabel, qxxLabel);
                il.Br(xxxLabel);
                il.MarkLabel(zzzLabel);
                il.Ldstr("zzz");
                il.Ret();
                il.MarkLabel(qxxLabel);
                il.Ldstr("qxx");
                il.Ret();
                il.MarkLabel(qzzLabel);
                il.Ldstr("qzz");
                il.Ret();
                il.MarkLabel(xxxLabel);
                il.Ldstr("xxx");
                il.Ret();
            }
            return((Func <int, string>)dynamicMethod.CreateDelegate(typeof(Func <int, string>)));
        }
        private static Func <object, object> EmitResolveVarArgsMethod()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(object) }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                var VarArgMethod_t = typeof(DynamicMethod).Assembly.GetType("System.Reflection.Emit.VarArgMethod");
                if (VarArgMethod_t == null)
                {
                    throw new InvalidOperationException("Missing type 'System.Reflection.Emit.VarArgMethod'");
                }
                il.Ldarg(0);               // stack: [value]
                il.Isinst(VarArgMethod_t); // stack: [(VarArgMethod)value]
                var retLabel = il.DefineLabel("ret");
                il.Dup();                  // stack: [(VarArgMethod)value, (VarArgMethod)value]
                il.Brfalse(retLabel);      // if(!(value is VarArgMethod)) goto ret; stack: [value as VarArgMethod]
                var m_method_f = VarArgMethod_t.GetField("m_method", BindingFlags.Instance | BindingFlags.NonPublic);
                if (m_method_f == null)
                {
                    throw new InvalidOperationException("Missing field 'System.Reflection.Emit.VarArgMethod.m_method'");
                }
                var m_dynamicMethod_f = VarArgMethod_t.GetField("m_dynamicMethod", BindingFlags.Instance | BindingFlags.NonPublic);
                if (m_dynamicMethod_f == null)
                {
                    throw new InvalidOperationException("Missing field 'System.Reflection.Emit.VarArgMethod.m_dynamicMethod'");
                }
                var temp = il.DeclareLocal(VarArgMethod_t);
                il.Dup();
                il.Stloc(temp);              // temp = (VarArgMethod)value; stack: [(VarArgMethod)value]
                il.Ldfld(m_method_f);        // stack: [((VarArgMethod)value).m_method]
                il.Dup();                    // stack: [((VarArgMethod)value).m_method, ((VarArgMethod)value).m_method]
                il.Brtrue(retLabel);         // if(((VarArgMethod)value).m_method != null) goto ret; stack: [((VarArgMethod)value).m_method]
                il.Pop();                    // stack: []
                il.Ldloc(temp);              // stack: [(VarArgMethod)value]
                il.Ldfld(m_dynamicMethod_f); // stack: [((VarArgMethod)value).m_dynamicMethod]
                il.MarkLabel(retLabel);
                il.Ret();
            }
            return((Func <object, object>)method.CreateDelegate(typeof(Func <object, object>)));
        }
        private static Func <object, object> EmitResolveGenericMethodInfo()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(object) }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                var GenericMethodInfo_t = typeof(DynamicMethod).Assembly.GetType("System.Reflection.Emit.GenericMethodInfo");
                if (GenericMethodInfo_t == null)
                {
                    throw new InvalidOperationException("Missing type 'System.Reflection.Emit.GenericMethodInfo'");
                }
                il.Ldarg(0);                    // stack: [value]
                il.Isinst(GenericMethodInfo_t); // stack: [(GenericMethodInfo)value]
                var retLabel = il.DefineLabel("ret");
                il.Dup();                       // stack: [(GenericMethodInfo)value, (GenericMethodInfo)value]
                il.Brfalse(retLabel);           // if(!(value is GenericMethodInfo)) goto ret; stack: [value as GenericMethodInfo]
                var m_methodHandle_f = GenericMethodInfo_t.GetField("m_methodHandle", BindingFlags.Instance | BindingFlags.NonPublic);
                if (m_methodHandle_f == null)
                {
                    throw new InvalidOperationException("Missing field 'System.Reflection.Emit.GenericMethodInfo.m_methodHandle'");
                }
                var m_context_f = GenericMethodInfo_t.GetField("m_context", BindingFlags.Instance | BindingFlags.NonPublic);
                if (m_context_f == null)
                {
                    throw new InvalidOperationException("Missing field 'System.Reflection.Emit.GenericMethodInfo.m_context'");
                }
                var temp = il.DeclareLocal(GenericMethodInfo_t);
                il.Dup();
                il.Stloc(temp);                 // temp = (GenericMethodInfo)value; stack: [(GenericMethodInfo)value]
                il.Ldfld(m_methodHandle_f);     // stack: [((GenericMethodInfo)value).m_methodHandle]
                il.Ldloc(temp);                 // stack: [((GenericMethodInfo)value).m_methodHandle, (GenericMethodInfo)value]
                il.Ldfld(m_context_f);          // stack: [((GenericMethodInfo)value).m_methodHandle, ((GenericMethodInfo)value).m_context]
                var getMethodFromHandle_m = HackHelpers.GetMethodDefinition <int>(x => MethodBase.GetMethodFromHandle(default(RuntimeMethodHandle), default(RuntimeTypeHandle)));
                il.Call(getMethodFromHandle_m); // stack: [MethodBase.GetMethodFromHandle(((GenericMethodInfo)value).m_methodHandle, ((GenericMethodInfo)value).m_context)]
                il.MarkLabel(retLabel);
                il.Ret();
            }
            return((Func <object, object>)method.CreateDelegate(typeof(Func <object, object>)));
        }
Esempio n. 11
0
        private Tuple <Action, MethodInfo> Build()
        {
            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(void), Type.EmptyTypes, Module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldfld(xField);
                il.Ldc_I4(1);
                il.Add();
                il.Stfld(xField);
                il.Ret();
            }
            return(new Tuple <Action, MethodInfo>((Action)dynamicMethod.CreateDelegate(typeof(Action)), dynamicMethod));
        }
Esempio n. 12
0
        private static MethodBuilder DefineMethodInterceptingDelegate(TypeBuilder typeBuilder, MethodInfo overridedMethod, Dictionary <Type, FieldInfo> interceptorFields, MethodInfo genericInterceptionAction, MethodInfo voidInterceptionAction, Type[] genericParameterTypes, MethodBuilder @delegate, int index, Type interceptor)
        {
            ConstructorInfo delegateConstructor;
            MethodInfo      interceptorMethod;

            // Define the method
            var method = typeBuilder.DefineMethod($"{overridedMethod.Name}-{interceptor.Name}_{index}_Interceptor",
                                                  MethodAttributes.Private | MethodAttributes.HideBySig,
                                                  overridedMethod.ReturnType,
                                                  new[] { typeof(ParamInfo[]) });

            SetupGenericMethodArguments(overridedMethod, method);

            using (var il = new GroboIL(method))
            {
                if (overridedMethod.ReturnType != typeof(void))
                {
                    interceptorMethod   = genericInterceptionAction.MakeGenericMethod(overridedMethod.ReturnType);
                    delegateConstructor = typeof(TDelegate <>).MakeGenericType(overridedMethod.ReturnType).GetConstructor(new[] { typeof(object), typeof(IntPtr) });
                }
                else
                {
                    interceptorMethod   = voidInterceptionAction;
                    delegateConstructor = typeof(VoidDelegate).GetConstructor(new[] { typeof(object), typeof(IntPtr) });
                }

                il.Ldarg(0);
                il.Ldfld(interceptorFields[interceptor]);
                il.Ldarg(0);

                if (overridedMethod.IsGenericMethodDefinition)
                {
                    il.Ldftn(@delegate.MakeGenericMethod(genericParameterTypes));
                }
                else
                {
                    il.Ldftn(@delegate);
                }

                il.Newobj(delegateConstructor);
                il.Ldarg(1);
                il.Call(interceptorMethod);
                il.Ret();

                @delegate = method;
            }

            return(@delegate);
        }
        public static void LoadReader(GroboIL il, Type type, ReaderTypeBuilderContext context)
        {
            var counter = context.GetReader(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));
            }
        }
        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) });
        }
Esempio n. 15
0
        private static void DefineMethodOverrideNoInterception(MethodBuilder methodBuilder, MethodInfo overridedMethod, FieldBuilder concreteInstance, ParameterInfo[] methodParams)
        {
            using (var il = new GroboIL(methodBuilder))
            {
                il.Ldarg(0);
                il.Ldfld(concreteInstance);
                foreach (var parameter in methodParams)
                {
                    il.Ldarg(parameter.Position + 1);
                }

                il.Call(overridedMethod);
                il.Ret();

                LogIlCode(il);
            }
        }
        private static Action <DebugInfoGenerator, LambdaExpression, MethodBase, GroboIL, DebugInfoExpression> BuildSequencePointMarker()
        {
            var parameterTypes = new[] { typeof(DebugInfoGenerator), typeof(LambdaExpression), typeof(MethodBase), typeof(GroboIL), typeof(DebugInfoExpression) };
            var dynamicMethod  = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), parameterTypes, typeof(DebugInfoExpressionEmitter), true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldarg(0);
                il.Ldarg(1);
                il.Ldarg(2);
                il.Ldarg(3);
                il.Ldfld(typeof(GroboIL).GetField("il", BindingFlags.NonPublic | BindingFlags.Instance));
                il.Ldarg(4);
                var markSequencePointMethod = typeof(DebugInfoGenerator).GetMethod("MarkSequencePoint", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(LambdaExpression), typeof(MethodBase), typeof(ILGenerator), typeof(DebugInfoExpression) }, null);
                il.Call(markSequencePointMethod, typeof(DebugInfoGenerator));
                il.Ret();
            }
            return((Action <DebugInfoGenerator, LambdaExpression, MethodBase, GroboIL, DebugInfoExpression>)dynamicMethod.CreateDelegate(typeof(Action <DebugInfoGenerator, LambdaExpression, MethodBase, GroboIL, DebugInfoExpression>)));
        }
Esempio n. 17
0
        private static void BuildChildren(TypeBuilder typeBuilder, int n, Context context)
        {
            var property = typeBuilder.DefineProperty("Children", PropertyAttributes.None, typeof(IEnumerable <MethodCallNode>), Type.EmptyTypes);
            var getter   = typeBuilder.DefineMethod("get_Children", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(IEnumerable <MethodCallNode>), Type.EmptyTypes);

            using (var il = new GroboIL(getter))
            {
                il.Ldc_I4(n);                      // stack: [n]
                il.Newarr(typeof(MethodCallNode)); // stack: [new int[n] -> values]
                for (int i = 0; i < n; ++i)
                {
                    il.Dup();                          // stack: [values, values]
                    il.Ldc_I4(i);                      // stack: [values, values, i]
                    il.Ldarg(0);                       // stack: [values, values, i, this]
                    il.Ldfld(context.values[i]);       // stack: [values, values, i, this.values_{i}]
                    il.Stelem(typeof(MethodCallNode)); // values[i] = this.values_{i}; stack: [values]
                }
                il.Castclass(typeof(IEnumerable <MethodCallNode>));
                il.Ret();
            }
            property.SetGetMethod(getter);
            typeBuilder.DefineMethodOverride(getter, typeof(MethodCallNodeEdges).GetProperty(property.Name, BindingFlags.Public | BindingFlags.Instance).GetGetMethod());
        }
Esempio n. 18
0
        private static EnumParserDelegate EmitEnumParser()
        {
            var method         = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(Type), typeof(string), typeof(bool) }, typeof(string), true);
            var il             = new GroboIL(method);
            var enumResultType = typeof(Enum).GetNestedType("EnumResult", BindingFlags.NonPublic);
            var enumResult     = il.DeclareLocal(enumResultType);

            il.Ldarg(0);
            il.Ldarg(1);
            il.Ldarg(2);
            il.Ldloca(enumResult);
            il.Call(typeof(Enum).GetMethod("TryParseEnum", BindingFlags.Static | BindingFlags.NonPublic));
            var returnNullLabel = il.DefineLabel("returnNull");

            il.Brfalse(returnNullLabel);
            il.Ldloca(enumResult);
            il.Ldfld(enumResultType.GetField("parsedEnum", BindingFlags.Instance | BindingFlags.NonPublic));
            il.Ret();
            il.MarkLabel(returnNullLabel);
            il.Ldnull();
            il.Ret();
            return((EnumParserDelegate)method.CreateDelegate(typeof(EnumParserDelegate)));
        }
Esempio n. 19
0
        public void GetWriteILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local value, GroboIL.Local typeSize, GroboIL.Local buffer, GroboIL.Local offset, bool listValue)
        {
            BinaryStruct.WriteSizeChecker(il, buffer, offset, 8);
            var v   = il.DeclareLocal(typeof(Vector2));
            var arr = il.DeclareLocal(typeof(byte[]));

            il.Ldloc(value);
            if (!listValue)
            {
                il.Call(prop.Getter);
            }
            il.Stloc(v);
            il.Ldloca(v);
            //il.Dup();
            //il.Box(typeof(Vector2));
            il.Ldfld(xField);

            //il.Dup();
            //il.Pop();
            il.Call(writeBitConverterMethodInfo);
            il.Stloc(arr);

            il.Ldloc(buffer);
            il.Ldloc(offset);
            il.Ldloc(arr);
            il.Ldc_I4(0);
            il.Ldelem(typeof(byte));
            il.Stelem(typeof(byte));

            for (int i = 1; i < 4; i++)
            {
                il.Ldloc(buffer);
                il.Ldloc(offset);
                il.Ldc_I4(i);
                il.Add();
                il.Ldloc(arr);
                il.Ldc_I4(i);
                il.Ldelem(typeof(byte));
                il.Stelem(typeof(byte));
            }
            BinaryStruct.WriteOffsetAppend(il, offset, 4);

            il.Ldloca(v);

            il.Ldfld(yField);
            il.Call(writeBitConverterMethodInfo);
            il.Stloc(arr);

            il.Ldloc(buffer);
            il.Ldloc(offset);
            il.Ldloc(arr);
            il.Ldc_I4(0);
            il.Ldelem(typeof(byte));
            il.Stelem(typeof(byte));

            for (int i = 1; i < 4; i++)
            {
                il.Ldloc(buffer);
                il.Ldloc(offset);
                il.Ldc_I4(i);
                il.Add();
                il.Ldloc(arr);
                il.Ldc_I4(i);
                il.Ldelem(typeof(byte));
                il.Stelem(typeof(byte));
            }
            BinaryStruct.WriteOffsetAppend(il, offset, 4);
        }
Esempio n. 20
0
 private void ValueLength() => Generator.Ldfld(Info.OfField <BitsValue>(nameof(BitsValue.Length)));
Esempio n. 21
0
        private static Type BuildTypeInternal(Type type)
        {
            var parentType  = typeof(ValidationResultTreeNode);
            var properties  = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            var typeBuilder = module.DefineType(type.Name + "_" + id++, TypeAttributes.Class | TypeAttributes.Public, parentType);

            typesBeingBuilt[type] = typeBuilder;

            var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { parentType });

            using (var il = new GroboIL(constructor))
            {
                il.Ldarg(0);              // stack: [this]
                il.Ldarg(1);              // stack: [this, parent]
                var baseConstructor = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { parentType }, null);
                il.Call(baseConstructor); // base(parent); stack: []
                il.Ret();
            }

            var fields = new Dictionary <string, FieldBuilder>();

            foreach (var property in properties)
            {
                var  propertyType = property.PropertyType;
                Type fieldType;
                if (propertyType.IsArray)
                {
                    fieldType = typeof(ValidationResultTreeArrayNode <>).MakeGenericType(BuildType(propertyType.GetElementType()));
                }
                else if (propertyType.IsDictionary() || propertyType == typeof(Hashtable))
                {
                    fieldType = typeof(ValidationResultTreeUniversalNode);
                }
                else
                {
                    fieldType = BuildType(propertyType, true);
                }
                var field = typeBuilder.DefineField(property.Name, fieldType, FieldAttributes.Public);
                fields.Add(property.Name, field);
            }

            var getChildrenMethod        = parentType.GetMethod("GetChildren", BindingFlags.Instance | BindingFlags.NonPublic);
            var getChildrenMethodBuilder = typeBuilder.DefineMethod(getChildrenMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(IEnumerable <KeyValuePair <object, ValidationResultTreeNode> >), Type.EmptyTypes);

            using (var il = new GroboIL(getChildrenMethodBuilder))
            {
                var listType        = typeof(List <KeyValuePair <object, ValidationResultTreeNode> >);
                var addMethod       = listType.GetMethod("Add", new[] { typeof(KeyValuePair <object, ValidationResultTreeNode>) });
                var itemConstructor = typeof(KeyValuePair <object, ValidationResultTreeNode>).GetConstructor(new[] { typeof(object), parentType });
                var list            = il.DeclareLocal(listType);
                il.Newobj(listType.GetConstructor(Type.EmptyTypes)); // stack: [new List<>()]
                il.Stloc(list);                                      // list = new List<>(); stack: []
                foreach (var field in fields.Values)
                {
                    il.Ldarg(0);                // stack: [this]
                    il.Ldfld(field);            // stack: [this.field]
                    var nextLabel = il.DefineLabel("next");
                    il.Brfalse(nextLabel);      // if(this.field == null) goto next; stack: []
                    il.Ldloc(list);             // stack: [list]
                    il.Ldstr(field.Name);       // stack: [list, field.Name]
                    il.Ldarg(0);                // stack: [list, field.Name, this]
                    il.Ldfld(field);            // stack: [list, field.Name, this.field]
                    il.Newobj(itemConstructor); // stack: [list, new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)]
                    il.Call(addMethod);         // list.Add(new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)); stack: []
                    il.MarkLabel(nextLabel);
                }

                il.Ldloc(list);
                il.Ret();
            }

            typeBuilder.DefineMethodOverride(getChildrenMethodBuilder, getChildrenMethod);

            var traverseEdgeMethod        = parentType.GetMethod("TraverseEdge", BindingFlags.Instance | BindingFlags.NonPublic);
            var traverseEdgeMethodBuilder = typeBuilder.DefineMethod(traverseEdgeMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, parentType, new[] { typeof(Expression) });

            using (var il = new GroboIL(traverseEdgeMethodBuilder))
            {
                il.Ldarg(1);                                                                   // stack: [edge]
                il.Castclass(typeof(MemberExpression));                                        // stack: [(MemberExpression)edge]
                il.Call(HackHelpers.GetProp <MemberExpression>(x => x.Member).GetGetMethod()); // stack: [((MemberExpresion)edge).Member]
                il.Call(HackHelpers.GetProp <MemberInfo>(x => x.Name).GetGetMethod());         // stack: [((MemberExpresion)edge).Member.Name]
                var member = il.DeclareLocal(typeof(string));
                il.Stloc(member);
                foreach (var property in properties)
                {
                    il.Ldstr(property.Name); // stack: [property.Name]
                    il.Ldloc(member);        // stack: [property.Name, member]
                    il.Call(typeof(string).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public));
                    var nextLabel = il.DefineLabel("next");
                    il.Brfalse(nextLabel);           // if(property.Name != member) goto next; stack: []
                    il.Ldarg(0);                     // stack: [this]
                    il.Ldfld(fields[property.Name]); // stack: [this.field]
                    il.Ret();                        // return this.field;
                    il.MarkLabel(nextLabel);
                }

                il.Ldnull();
                il.Ret();
            }

            typeBuilder.DefineMethodOverride(traverseEdgeMethodBuilder, traverseEdgeMethod);

            var result = typeBuilder.CreateTypeInfo();

            typesBeingBuilt[type] = null;
            return(result);
        }
Esempio n. 22
0
        private KeyValuePair <Delegate, IntPtr> GetMemberSetter(ReaderTypeBuilderContext context, MemberInfo member)
        {
            var method = new DynamicMethod("Set_" + Type.Name + "_" + member.Name + "_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext)
            }, context.Module, true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0); // stack: [data]
                il.Ldarg(1); // stack: [data, ref index]
                switch (member.MemberType)
                {
                case MemberTypes.Field:
                    var field = (FieldInfo)member;
                    var done  = false;
                    if (member.GetCustomAttributes(typeof(IgnoreDefaultOnMergeAttribute), false).Length > 0 && field.FieldType.IsValueType)
                    {
                        var equalityOperator = field.FieldType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
                        if (field.FieldType.IsPrimitive || equalityOperator != null)
                        {
                            var fieldValue = il.DeclareLocal(field.FieldType);
                            il.Ldarg(2); // stack: [data, ref index, ref result]
                            if (!Type.IsValueType)
                            {
                                il.Ldind(Type); // stack: [data, ref index, result]
                            }
                            il.Ldfld(field);
                            il.Stloc(fieldValue);
                            il.Ldloca(fieldValue);
                            il.Ldarg(3);                                                         // stack: [data, ref index, ref result.field, context]
                            ReaderMethodBuilderContext.CallReader(il, field.FieldType, context); // reader(data, ref index, ref result.field, context); stack: []

                            var temp = il.DeclareLocal(field.FieldType);
                            il.Ldloca(temp);
                            il.Initobj(field.FieldType);
                            il.Ldloc(temp);
                            il.Ldloc(fieldValue);
                            if (field.FieldType.IsPrimitive)
                            {
                                il.Ceq();
                            }
                            else
                            {
                                il.Call(equalityOperator);
                            }
                            var notDefaultLabel = il.DefineLabel("notDefault");
                            il.Brfalse(notDefaultLabel);
                            il.Ret();
                            il.MarkLabel(notDefaultLabel);
                            il.Ldarg(2);
                            if (!Type.IsValueType)
                            {
                                il.Ldind(Type); // stack: [data, ref index, result]
                            }
                            il.Ldloc(fieldValue);
                            il.Stfld(field);
                            done = true;
                        }
                    }
                    if (!done)
                    {
                        il.Ldarg(2); // stack: [data, ref index, ref result]
                        if (!Type.IsValueType)
                        {
                            il.Ldind(Type);                                                  // stack: [data, ref index, result]
                        }
                        il.Ldflda(field);                                                    // stack: [data, ref index, ref result.field]
                        il.Ldarg(3);                                                         // stack: [data, ref index, ref result.field, context]
                        ReaderMethodBuilderContext.CallReader(il, field.FieldType, context); // reader(data, ref index, ref result.field, context); stack: []
                    }
                    break;

                case MemberTypes.Property:
                    var property      = (PropertyInfo)member;
                    var propertyValue = il.DeclareLocal(property.PropertyType);
                    if (context.GroBufReader.Options.HasFlag(GroBufOptions.MergeOnRead))
                    {
                        var getter = property.GetGetMethod(true);
                        if (getter == null)
                        {
                            throw new MissingMethodException(Type.Name, property.Name + "_get");
                        }
                        il.Ldarg(2); // stack: [data, ref index, ref result]
                        if (!Type.IsValueType)
                        {
                            il.Ldind(Type);                                                    // stack: [data, ref index, result]
                        }
                        il.Call(getter, Type);                                                 // stack: [ data, ref index, result.property]
                        il.Stloc(propertyValue);                                               // propertyValue = result.property; stack: [data, ref index]
                    }
                    il.Ldloca(propertyValue);                                                  // stack: [data, ref index, ref propertyValue]
                    il.Ldarg(3);                                                               // stack: [data, ref index, ref propertyValue, context]
                    ReaderMethodBuilderContext.CallReader(il, property.PropertyType, context); // reader(data, ref index, ref propertyValue, context); stack: []
                    if (member.GetCustomAttributes(typeof(IgnoreDefaultOnMergeAttribute), false).Length > 0 && property.PropertyType.IsValueType)
                    {
                        var equalityOperator = property.PropertyType.GetMethod("op_Equality", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
                        if (property.PropertyType.IsPrimitive || equalityOperator != null)
                        {
                            var temp = il.DeclareLocal(property.PropertyType);
                            il.Ldloca(temp);
                            il.Initobj(property.PropertyType);
                            il.Ldloc(temp);
                            il.Ldloc(propertyValue);
                            if (property.PropertyType.IsPrimitive)
                            {
                                il.Ceq();
                            }
                            else
                            {
                                il.Call(equalityOperator);
                            }
                            var notDefaultLabel = il.DefineLabel("notDefault");
                            il.Brfalse(notDefaultLabel);
                            il.Ret();
                            il.MarkLabel(notDefaultLabel);
                        }
                    }
                    il.Ldarg(2); // stack: [ref result]
                    if (!Type.IsValueType)
                    {
                        il.Ldind(Type);      // stack: [result]
                    }
                    il.Ldloc(propertyValue); // stack: [result, propertyValue]
                    var setter = property.GetSetMethod(true);
                    if (setter == null)
                    {
                        throw new MissingMethodException(Type.Name, property.Name + "_set");
                    }
                    il.Call(setter, Type); // result.property = propertyValue
                    break;

                default:
                    throw new NotSupportedException("Data member of type '" + member.MemberType + "' is not supported");
                }
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type));

            return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method)));
        }
Esempio n. 23
0
        public static TryGetValueDelegate <T> Build <T>(char[] keys, T[] values, int numberOfSegments, int numberOfKeysPerSegment)
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool),
                                           new[] { typeof(Closure <T>), typeof(char), typeof(T).MakeByRefType() }, typeof(string), true);
            var indices = new List <int>();

            using (var il = new GroboIL(method))
            {
                var idx           = il.DeclareLocal(typeof(int), "idx");
                var retFalseLabel = il.DefineLabel("retFalse");
                for (int i = 0; i < numberOfSegments; ++i)
                {
                    var firstKeyInSegment = keys[i * numberOfKeysPerSegment];
                    var lastKeyInSegment  = keys[numberOfKeysPerSegment - 1 + i * numberOfKeysPerSegment];
                    il.Ldarg(1);                                                   // stack: [key]
                    il.Ldc_I4(firstKeyInSegment);                                  // stack: [key, firstKey]
                    var nextSegmentLabel = il.DefineLabel("nextSegment");
                    il.Blt(nextSegmentLabel, false);                               // if(key < firstKey) goto nextSegment; stack: []
                    il.Ldarg(1);                                                   // stack: [key]
                    il.Ldc_I4(lastKeyInSegment);                                   // stack: [key, lastKey]
                    il.Bgt(nextSegmentLabel, false);                               // if(key > lastKey) goto nextSegment; stack: []
                    il.Ldarg(0);                                                   // stack: [closure]
                    il.Ldfld(HackHelpers.GetField <Closure <T> >(x => x.indices)); // stack: [closure.indices]
                    il.Ldarg(1);                                                   // stack: [closure.indices, key]
                    il.Ldc_I4(firstKeyInSegment - indices.Count);                  // stack: [closure.indices, key, diff]
                    il.Sub();                                                      // stack: [closure.indices, key - diff]
                    il.Ldelem(typeof(int));                                        // stack: [closure.indices[key - diff]]
                    il.Dup();
                    il.Stloc(idx);                                                 // idx = closure.indices[key - diff]; stack: [idx]
                    il.Ldc_I4(0);                                                  // stack: [idx, 0]
                    il.Blt(retFalseLabel, false);                                  // if(idx < 0) goto retFalse; stack: []
                    il.Ldarg(2);                                                   // stack: [ref value]
                    il.Ldarg(0);                                                   // stack: [ref value, closure]
                    il.Ldfld(HackHelpers.GetField <Closure <T> >(x => x.values));  // stack: [ref value, closure.values]
                    il.Ldloc(idx);                                                 // stack: [ref value, closure.values, idx]
                    il.Ldelem(typeof(T));                                          // stack: [ref value, closure.values[idx]]
                    il.Stind(typeof(T));                                           // value = closure.values[idx]; stack: []
                    il.Ldc_I4(1);                                                  // stack: [true]
                    il.Ret();
                    il.MarkLabel(nextSegmentLabel);
                    var segmentLength = lastKeyInSegment - firstKeyInSegment + 1;
                    int start         = indices.Count;
                    for (int j = 0; j < segmentLength; ++j)
                    {
                        indices.Add(-1);
                    }
                    for (int j = 0; j < numberOfKeysPerSegment; ++j)
                    {
                        indices[start + keys[i * numberOfKeysPerSegment + j] - firstKeyInSegment] = i * numberOfKeysPerSegment + j;
                    }
                }
                il.MarkLabel(retFalseLabel);
                il.Ldarg(2); // stack: [ref value]
                if (typeof(T).IsValueType)
                {
                    il.Initobj(typeof(T)); // value = default(T); stack: []
                }
                else
                {
                    il.Ldnull();         // stack: [ref value, null]
                    il.Stind(typeof(T)); // value = null; stack: []
                }
                il.Ldc_I4(0);            // stack: [false]
                il.Ret();
            }
            var closure = new Closure <T>
            {
                indices = indices.ToArray(),
                values  = values
            };

            return((TryGetValueDelegate <T>)method.CreateDelegate(typeof(TryGetValueDelegate <T>), closure));
        }
Esempio n. 24
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());
        }
Esempio n. 25
0
        public void BuildReader(ReaderTypeBuilderContext readerTypeBuilderContext)
        {
            var method = new DynamicMethod("Read_" + Type.Name + "_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext)
            }, readerTypeBuilderContext.Module, true);

            readerTypeBuilderContext.SetReaderMethod(Type, method);
            using (var il = new GroboIL(method))
            {
                var context = new ReaderMethodBuilderContext(readerTypeBuilderContext, il, !Type.IsValueType && IsReference);

                ReadTypeCodeAndCheck(context); // Read TypeCode and check

                if (!Type.IsValueType && IsReference)
                {
                    // Read reference
                    context.LoadContext();                // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
                    var notReadLabel = il.DefineLabel("notRead");
                    il.Brfalse(notReadLabel);
                    context.LoadIndex();                  // stack: [external index]
                    context.LoadContext();                // stack: [external index, context]
                    il.Ldfld(ReaderContext.StartField);   // stack: [external index, context.start]
                    il.Sub();                             // stack: [external index - context.start]
                    il.Stloc(context.Index);              // index = external index - context.start; stack: []

                    context.LoadContext();                // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
                    il.Ldloc(context.Index);              // stack: [context.objects, index]
                    var obj = il.DeclareLocal(typeof(object));
                    il.Ldloca(obj);
                    object dummy;
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(index, out obj)]
                    il.Brfalse(notReadLabel);                                                                                     // if(!context.objects.TryGetValue(index, out obj)) goto notRead;
                    context.LoadResultByRef();                                                                                    // stack: [ref result]
                    il.Ldloc(obj);                                                                                                // stack: [ref result, obj]
                    il.Castclass(Type);                                                                                           // stack: [ref result, (Type)obj]
                    il.Stind(Type);                                                                                               // result = (Type)obj; stack: []
                    context.IncreaseIndexBy1();                                                                                   // Skip type code
                    context.SkipValue();                                                                                          // Skip value - it has already been read
                    il.Ret();
                    il.MarkLabel(notReadLabel);
                    il.Ldloc(context.TypeCode);               // stack: [typeCode]
                    il.Ldc_I4((int)GroBufTypeCode.Reference); // stack: [typeCode, GroBufTypeCode.Reference]
                    var readUsualLabel = il.DefineLabel("readUsual");
                    il.Bne_Un(readUsualLabel);                // if(typeCode != GroBufTypeCode.Reference) goto readUsual; stack: []

                    context.LoadContext();                    // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField);     // stack: [context.objects]
                    var objectsIsNotNullLabel = il.DefineLabel("objectsIsNotNull");
                    il.Brtrue(objectsIsNotNullLabel);         // if(context.objects != null) goto objectsIsNotNull; stack: [context.objects]
                    il.Ldstr("Reference is not valid at this point");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(objectsIsNotNullLabel);

                    context.IncreaseIndexBy1(); // index = index + 1; stack: []
                    il.Ldc_I4(4);
                    context.AssertLength();
                    context.GoToCurrentLocation();
                    var reference = il.DeclareLocal(typeof(int));
                    il.Ldind(typeof(int));             // stack: [*(int*)data[index]]
                    il.Stloc(reference);               // reference = *(int*)data[index]; stack: []
                    context.IncreaseIndexBy4();        // index = index + 4; stack: []
                    il.Ldloc(context.Index);           // stack: [index]
                    il.Ldloc(reference);               // stack: [index, reference]
                    var goodReferenceLabel = il.DefineLabel("goodReference");
                    il.Bgt(goodReferenceLabel, false); // if(index > reference) goto goodReference; stack: []
                    il.Ldstr("Bad reference");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(goodReferenceLabel);
                    context.LoadContext();                                                                                        // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField);                                                                         // stack: [context.objects]
                    il.Ldloc(reference);                                                                                          // stack: [context.objects, reference]
                    il.Ldloca(obj);                                                                                               // stack: [context.objects, reference, ref obj]
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(reference, out obj)]
                    var readObjectLabel = il.DefineLabel("readObject");
                    il.Brfalse(readObjectLabel);                                                                                  // if(!context.objects.TryGetValue(reference, out obj)) goto readObjects; stack: []
                    context.LoadResultByRef();                                                                                    // stack: [ref result]
                    il.Ldloc(obj);                                                                                                // stack: [ref result, obj]
                    il.Castclass(Type);                                                                                           // stack: [ref result, (Type)obj]
                    il.Stind(Type);                                                                                               // result = (Type)obj; stack: []
                    il.Ret();
                    il.MarkLabel(readObjectLabel);

                    // Referenced object has not been read - this means that the object reference belongs to is a property that had been deleted
                    context.LoadData();                 // stack: [data]
                    il.Ldloc(reference);                // stack: [data, reference]
                    context.LoadContext();              // stack: [data, reference, context]
                    il.Ldfld(ReaderContext.StartField); // stack: [data, reference, context.start]
                    il.Add();                           // stack: [data, reference + context.start]
                    il.Stloc(reference);                // reference += context.start; stack: [data]
                    il.Ldloca(reference);               // stack: [data, ref reference]
                    context.LoadResultByRef();          // stack: [data, ref reference, ref result]
                    context.LoadContext();              // stack: [data, ref reference, ref result, context]
                    context.CallReader(Type);
                    il.Ret();
                    il.MarkLabel(readUsualLabel);
                }

                ReadNotEmpty(context); // Read obj
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type));
            var pointer   = GroBufHelpers.ExtractDynamicMethodPointer(method);

            readerTypeBuilderContext.SetReaderPointer(Type, pointer, @delegate);
        }
Esempio n. 26
0
        private static MethodBuilder GenerateOverloadedMethodDelegate(MethodInfo methodToIntercept,
                                                                      TypeBuilder typeBuilder,
                                                                      FieldInfo concrete)
        {
            // Define the method
            var method = typeBuilder.DefineMethod(methodToIntercept.Name + "-Delegate",
                                                  MethodAttributes.Private | MethodAttributes.HideBySig,
                                                  methodToIntercept.ReturnType,
                                                  new[] { typeof(ParamInfo[]) });

            SetupGenericMethodArguments(methodToIntercept, method);

            // Local for each out/ref parameter
            var parameters = methodToIntercept.GetParameters();

            var locals = new Dictionary <string, Local>();

            using (var il = new GroboIL(method))
            {
                foreach (ParameterInfo parameter in parameters)
                {
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        locals.Add(parameter.Name, il.DeclareLocal(parameter.ParameterType.GetElementType(), parameter.Name));
                    }
                }

                var paramInfoType     = typeof(ParamInfo);
                var paramInfoGetValue = paramInfoType.GetProperty("Value").GetGetMethod();

                // Initialize out parameters to default values
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].ParameterType.IsByRef && !parameters[i].IsOut)
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoGetValue);

                        if (parameters[i].ParameterType.GetElementType().IsValueType)
                        {
                            il.Unbox_Any(parameters[i].ParameterType.GetElementType());
                        }
                        else
                        {
                            il.Castclass(parameters[i].ParameterType.GetElementType());
                        }

                        il.Stloc(locals[parameters[i].Name]);
                    }
                }

                // Load target
                il.Ldarg(0);
                il.Ldfld(concrete);

                // Push call values onto stack
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef)
                    {
                        il.Ldloca(locals[parameters[i].Name]);
                    }
                    else
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoGetValue);

                        if (parameters[i].ParameterType.IsValueType || parameters[i].ParameterType.IsGenericParameter)
                        {
                            il.Unbox_Any(parameters[i].ParameterType);
                        }
                        else
                        {
                            il.Castclass(parameters[i].ParameterType);
                        }
                    }
                }

                // Call intercepted method
                il.Call(methodToIntercept);

                var paramInfoSetValue = paramInfoType.GetProperty("Value").GetSetMethod();

                // Copy out/ref parameter values back into passed-in parameters array
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef)
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Ldloc(locals[parameters[i].Name]);

                        if (parameters[i].ParameterType.GetElementType().IsValueType)
                        {
                            il.Box(parameters[i].ParameterType.GetElementType());
                        }

                        il.Call(paramInfoSetValue);
                    }
                }

                il.Ret();

                LogIlCode(il);
            }

            return(method);
        }
Esempio n. 27
0
        public void BuildWriter(WriterTypeBuilderContext writerTypeBuilderContext)
        {
            var method = new DynamicMethod("Write_" + Type.Name + "_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                Type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext)
            }, writerTypeBuilderContext.Module, true);

            writerTypeBuilderContext.SetWriterMethod(Type, method);
            using (var il = new GroboIL(method))
            {
                var context = new WriterMethodBuilderContext(writerTypeBuilderContext, il);

                var notEmptyLabel = il.DefineLabel("notEmpty");
                if (CheckEmpty(context, notEmptyLabel)) // Check if obj is empty
                {
                    context.WriteNull();                // Write null & return
                }
                il.MarkLabel(notEmptyLabel);            // Now we know that obj is not empty

                if (!Type.IsValueType && IsReference && writerTypeBuilderContext.GroBufWriter.Options.HasFlag(GroBufOptions.PackReferences))
                {
                    // Pack reference
                    var index = il.DeclareLocal(typeof(int));
                    context.LoadIndex();                                                                                             // stack: [external index]
                    context.LoadContext();                                                                                           // stack: [external index, context]
                    il.Ldfld(WriterContext.StartField);                                                                              // stack: [external index, context.start]
                    il.Sub();                                                                                                        // stack: [external index - context.start]
                    il.Stloc(index);                                                                                                 // index = external index - context.start; stack: []
                    context.LoadContext();                                                                                           // stack: [context]
                    il.Ldfld(typeof(WriterContext).GetField("objects", BindingFlags.Public | BindingFlags.Instance));                // stack: [context.objects]
                    context.LoadObj();                                                                                               // stack: [context.objects, obj]
                    var reference = il.DeclareLocal(typeof(int));
                    il.Ldloca(reference);                                                                                            // stack: [context.objects, obj, ref reference]
                    int dummy;
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.TryGetValue(null, out dummy))); // stack: [context.object.TryGetValue(obj, out reference)]
                    var storeLocationLabel = il.DefineLabel("storeLocation");
                    il.Brfalse(storeLocationLabel);
                    // Current object is in dict
                    il.Ldloc(index);
                    il.Ldloc(reference);                             // stack: [index, reference]
                    var skipSelfLabel = il.DefineLabel("skipSelf");
                    il.Beq(skipSelfLabel);                           // if(index == reference) goto skipSelf; stack: []
                    il.Ldloc(index);                                 // stack: [index]
                    il.Ldloc(reference);                             // stack: [index, reference]
                    var badReferenceLabel = il.DefineLabel("badReference");
                    il.Blt(badReferenceLabel, false);                // if(index < reference) goto badReference; stack: []
                    context.WriteTypeCode(GroBufTypeCode.Reference); // result[index++] = GroBufTypeCode.Reference
                    context.GoToCurrentLocation();                   // stack: [&result[index]]
                    il.Ldloc(reference);                             // stack: [&result[index], reference]
                    il.Stind(typeof(int));                           // *(int *)&result[index] = reference
                    context.IncreaseIndexBy4();                      // index += 4
                    il.Ret();
                    il.MarkLabel(badReferenceLabel);
                    il.Ldstr("Bad reference");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(storeLocationLabel);
                    context.LoadContext();                                                                            // stack: [context]
                    il.Ldfld(typeof(WriterContext).GetField("objects", BindingFlags.Public | BindingFlags.Instance)); // stack: [context.objects]
                    context.LoadObj();                                                                                // stack: [context.objects, obj]
                    il.Ldloc(index);                                                                                  // stack: [context.objects, obj, index]
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <object, int> >(dict => dict.Add(null, 0)));  // context.objects.Add(obj, index);
                    il.MarkLabel(skipSelfLabel);
                }

                WriteNotEmpty(context); // Write obj
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(WriterDelegate <>).MakeGenericType(Type));
            var pointer   = GroBufHelpers.ExtractDynamicMethodPointer(method);

            writerTypeBuilderContext.SetWriterPointer(Type, pointer, @delegate);
        }
Esempio n. 28
0
        private static Action <Hashtable, Array, int> EmitCopyValues()
        {
            /*
             * private void CopyValues(Hashtable hashtable, Array array, int arrayLength)
             * {
             *  bucket[] buckets = hashtable.buckets;
             *  int length = buckets.Length;
             *  int arrayIndex = 0;
             *  while (--length >= 0)
             *  {
             *      object key = buckets[length].key;
             *      if ((key != null) && (key != hashtable.buckets))
             *      {
             *          if (arrayIndex >= arrayLength)
             *              return;
             *          array.SetValue(buckets[length].val, arrayIndex++);
             *      }
             *  }
             * }
             */
            var dynamicMethod = new DynamicMethod(
                Guid.NewGuid().ToString(), typeof(void), new[] { typeof(Hashtable), typeof(Array), typeof(int) },
                typeof(Hashtable), true);

            var bucketsFieldInfo = typeof(Hashtable).GetField("buckets",
                                                              BindingFlags.Instance | BindingFlags.NonPublic);
            var bucketType      = typeof(Hashtable).GetNestedType("bucket", BindingFlags.NonPublic);
            var bucketArrayType = bucketType.MakeArrayType();

            var keyFieldInfo       = bucketType.GetField("key", BindingFlags.Instance | BindingFlags.Public);
            var valFieldInfo       = bucketType.GetField("val", BindingFlags.Instance | BindingFlags.Public);
            var setValueMethodInfo = typeof(Array).GetMethod("SetValue", new[] { typeof(object), typeof(int) });

            using (var il = new GroboIL(dynamicMethod))
            {
                var buckets    = il.DeclareLocal(bucketArrayType, "buckets");
                var length     = il.DeclareLocal(typeof(int), "length");
                var arrayIndex = il.DeclareLocal(typeof(int), "arrayIndex");
                var key        = il.DeclareLocal(typeof(object), "key");

                var cycleStartLabel = il.DefineLabel("cycleStart");
                var cycleNextLabel  = il.DefineLabel("cycleNext");
                var endLabel        = il.DefineLabel("end");

                il.EmitSetIntToZero(arrayIndex);

                il.Ldarg(0);                // stack: hashtable
                il.Ldfld(bucketsFieldInfo); // stack: hashtable::buckets
                il.Stloc(buckets);

                il.Ldloc(buckets);     // stack: hashtable::buckets
                il.Ldlen();            // stack: buckets.length
                il.Conv <int>();       // stack: buckets.length (i4)
                il.Stloc(length);
                il.Br(cycleNextLabel); // jump(cycleNext)

                il.MarkLabel(cycleStartLabel);

                il.EmitLoadArrayItemRef(buckets, length, bucketType); // stack: *bucket[current]

                il.Ldfld(keyFieldInfo);                               // stack: key
                il.Stloc(key);                                        // 2: key
                il.Ldloc(key);                                        // stack: key
                il.Brfalse(cycleNextLabel);                           // jump(cycleNext) if key == null
                il.Ldloc(key);                                        // stack: key
                il.Ldarg(0);                                          // stack+: hashtable
                il.Ldfld(bucketsFieldInfo);                           // stack: key, hashtable::buckets
                il.Beq(cycleNextLabel);
                // jump(cycleNext) if key == hashtable::buckets (какой-то хитрый хак hashtable-а)

                il.Ldloc(arrayIndex);                                 // stack: arrayIndex
                il.Ldarg(2);                                          // stack+: arrayLength
                il.Bge(endLabel, false);                              // jump(end) if arrayIndex >= arrayLength

                il.Ldarg(1);                                          // stack: array (arg1)

                il.EmitLoadArrayItemRef(buckets, length, bucketType); // stack: array (arg1), *bucket[current]
                il.Ldfld(valFieldInfo);                               // stack: array (arg1), bucket[current].val
                il.EmitXPlusPlus(arrayIndex);                         // stack: array (arg1), bucket[current].val, arrayIndex++

                il.Call(setValueMethodInfo);                          // array.SetValue(bucket[current].val, old_arrayIndex);

                il.MarkLabel(cycleNextLabel);

                il.EmitMinusMinusX(length);     // stack: --current
                il.Ldc_I4(0);                   // stack+: 0
                il.Bge(cycleStartLabel, false); // jump(cycleStart) if --current >= 0

                il.MarkLabel(endLabel);
                il.Ret();
            }

            return((Action <Hashtable, Array, int>)dynamicMethod.CreateDelegate(typeof(Action <Hashtable, Array, int>)));
        }
Esempio n. 29
0
        private IQxx BuildSwitch(ModuleBuilder module, string[] keys)
        {
            var numberOfCases = keys.Length;
            var typeBuilder   = module.DefineType("Switch" + Guid.NewGuid(), TypeAttributes.Class | TypeAttributes.Public);

            typeBuilder.AddInterfaceImplementation(typeof(IQxx));
            var fields = new FieldInfo[numberOfCases];

            for (var i = 0; i < numberOfCases; ++i)
            {
                fields[i] = typeBuilder.DefineField(keys[i], typeof(int), FieldAttributes.Public);
            }
            var tinyHashtable = Create(keys);
            var n             = tinyHashtable.Length;
            var keysField     = typeBuilder.DefineField("keys", typeof(string[]), FieldAttributes.Public);
            var constructor   = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(string[]) });

            using (var il = new GroboIL(constructor))
            {
                il.Ldarg(0);
                il.Ldarg(1);
                il.Stfld(keysField);
                il.Ret();
            }

            var method = typeBuilder.DefineMethod("Set", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), new[] { typeof(string), typeof(int) });

            method.DefineParameter(1, ParameterAttributes.In, "key");
            method.DefineParameter(2, ParameterAttributes.In, "value");
            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                il.Ldfld(keysField);
                il.Ldarg(1);
                il.Call(HackHelpers.GetMethodDefinition <object>(o => o.GetHashCode()));
                il.Ldc_I4(n);
                il.Rem(true);
                var idx = il.DeclareLocal(typeof(int));
                il.Dup();
                il.Stloc(idx);
                il.Ldelem(typeof(string));
                il.Ldarg(1);
                il.Call(stringEqualityOperator);
                var doneLabel = il.DefineLabel("done");
                il.Brfalse(doneLabel);

                var labels = new GroboIL.Label[n];
                for (var i = 0; i < n; ++i)
                {
                    labels[i] = doneLabel;
                }
                foreach (var key in keys)
                {
                    var index = key.GetHashCode() % n;
                    if (index < 0)
                    {
                        index += n;
                    }
                    var label = il.DefineLabel("set_" + key);
                    labels[index] = label;
                }
                il.Ldloc(idx);
                il.Switch(labels);
                for (var i = 0; i < keys.Length; ++i)
                {
                    var index = keys[i].GetHashCode() % n;
                    if (index < 0)
                    {
                        index += n;
                    }
                    il.MarkLabel(labels[index]);
                    il.Ldarg(0);
                    il.Ldarg(2);
                    il.Stfld(fields[i]);
                    il.Br(doneLabel);
                }
                il.MarkLabel(doneLabel);
                il.Ret();
            }
            typeBuilder.DefineMethodOverride(method, typeof(IQxx).GetMethod("Set"));
            var type = typeBuilder.CreateType();

            return((IQxx)Activator.CreateInstance(type, new object[] { tinyHashtable }));
        }