public void EmitEncode(ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoad) { var valueIsNotNullLabel = il.DefineLabel(); var endOfMethodLabel = il.DefineLabel(); var elemVar = il.DeclareLocal(elementType); // TElement elem emitLoad(il); // if (value) il.Emit(OpCodes.Brtrue, valueIsNotNullLabel); // goto valueIsNotNullLabel // value is null branch il.Emit(OpCodes.Ldloc, locals.DataPointer); // *(int*) data = -1 il.Emit_Ldc_I4(-1); il.Emit(OpCodes.Stind_I4); il.Emit_IncreasePointer(locals.DataPointer, sizeof(int)); // data += sizeof(int) il.Emit(OpCodes.Br, endOfMethodLabel); // goto endOfMethodLabel // value is not null branch il.MarkLabel(valueIsNotNullLabel); // label valueIsNotNullLabel il.Emit(OpCodes.Ldloc, locals.DataPointer); // *(int*) data = (int)value.Count EmitLoadCount(il, emitLoad); il.Emit(OpCodes.Stind_I4); il.Emit_IncreasePointer(locals.DataPointer, sizeof(int)); // data += sizeof(int) EmitEnumerateCollection(il, emitLoad, emitLoadCurrent => // foreach (current in value) { emitLoadCurrent(); // elem = current il.Emit(OpCodes.Stloc, elemVar); elementCodec.EmitEncode(il, locals, elemVar); // encode(data, elem) }); il.MarkLabel(endOfMethodLabel); // label endOfMethodLabel }
public void EmitEncode(IEmittingContext context, Action <MyILGenerator> emitLoad) { var il = context.IL; var valueIsNotNullLabel = il.DefineLabel(); var endOfMethodLabel = il.DefineLabel(); var elemVar = il.DeclareLocal(elementType); // TElement elem emitLoad(il); // if (value) il.Brtrue(valueIsNotNullLabel); // goto valueIsNotNullLabel // value is null branch il.Ldloc(context.DataPointerVar); // *(int*) data = -1 il.Ldc_I4(-1); il.Stind_I4(); il.IncreasePointer(context.DataPointerVar, sizeof(int)); // data += sizeof(int) il.Br(endOfMethodLabel); // goto endOfMethodLabel // value is not null branch il.MarkLabel(valueIsNotNullLabel); // label valueIsNotNullLabel il.Ldloc(context.DataPointerVar); // *(int*) data = (int)value.Count EmitLoadCount(il, emitLoad); il.Stind_I4(); il.IncreasePointer(context.DataPointerVar, sizeof(int)); // data += sizeof(int) using (var loop = il.EmitForeachLoop(elementType, emitLoad)) // foreach (current in value) { loop.LoadCurrent(); // elem = current il.Stloc(elemVar); elementCodec.EmitEncode(context, elemVar); // encode(data, elem) } il.MarkLabel(endOfMethodLabel); // label endOfMethodLabel }
public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, Action <ILGenerator> emitLoadParent, MethodInfo propertyGetter) { codec.EmitEncode(il, locals, lil => { emitLoadParent(lil); lil.Emit(OpCodes.Call, propertyGetter); }); }
private DynamicMethod EmitEncode() { var dynamicMethod = new DynamicMethod("_encode_manual_" + type.FullName, typeof(void), new[] { typeof(byte *).MakeByRefType(), type }, Assembly.GetExecutingAssembly().ManifestModule, true); var il = dynamicMethod.GetILGenerator(); var locals = new LocalVariableCollection(il, false); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldind_I); il.Emit(OpCodes.Stloc, locals.DataPointer); emittingCodec.EmitEncode(il, locals, 1); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc, locals.DataPointer); il.Emit(OpCodes.Stind_I); il.Emit(OpCodes.Ret); return(dynamicMethod); }
private DynamicMethod EmitEncode() { const int codecContainerArgIndex = 0; const int dataArgIndex = 1; const int valueArgIndex = 2; var dynamicMethod = new DynamicMethod("_encode_manual_" + type.FullName, typeof(void), new[] { typeof(ICodecContainer), typeof(byte *).MakeByRefType(), type }, Assembly.GetExecutingAssembly().ManifestModule, true); var il = new MyILGenerator(dynamicMethod.GetILGenerator()); var context = new ManualCodecEmittingContext(il, codecContainerArgIndex); il.Ldarg(dataArgIndex); il.Ldind_I(); il.Stloc(context.DataPointerVar); emittingCodec.EmitEncode(context, valueArgIndex); il.Ldarg(dataArgIndex); il.Ldloc(context.DataPointerVar); il.Stind_I(); il.Ret(); return(dynamicMethod); }
public void EmitEncode(IEmittingContext emittingContext) { codec.EmitEncode(emittingContext, emitLoad); }
public static void EmitEncode(this IEmittingCodec codec, IEmittingContext context, Action <MyILGenerator> emitLoadParent, MethodInfo propertyGetter) { codec.EmitEncode(context, il => { emitLoadParent(il); il.Call(propertyGetter); }); }
public static void EmitEncode(this IEmittingCodec codec, IEmittingContext context, LocalBuilder localVar) { codec.EmitEncode(context, il => il.Ldloc(localVar)); }
public static void EmitEncodeIndirect(this IEmittingCodec codec, IEmittingContext context, int argIndex, Type type) { codec.EmitEncode(context, il => { il.Ldarg(argIndex); il.Ldobj(type); }); }
public static void EmitEncode(this IEmittingCodec codec, IEmittingContext context, int argIndex) { codec.EmitEncode(context, il => il.Ldarg(argIndex)); }
public ServiceMethodHandler CreateMethodHandler(ServiceImplementationInfo serviceImplementationInfo, ServicePath servicePath) { var serviceInterface = serviceImplementationInfo.Description.Type; var dynamicMethod = new DynamicMethod( "__srpc__handle__" + serviceInterface.FullName + "__" + string.Join("_", servicePath), typeof(byte[]), ParameterTypes, Assembly.GetExecutingAssembly().ManifestModule, true); var il = dynamicMethod.GetILGenerator(); var locals = new LocalVariableCollection(il, true); il.Emit(OpCodes.Ldarg_0); // stack_0 = (TServiceImplementation) arg_0 il.Emit(OpCodes.Castclass, serviceInterface); var serviceDesc = serviceImplementationInfo.Description; for (int i = 1; i < servicePath.Length - 1; i++) { var propertyInfo = serviceDesc.Type.GetProperty(servicePath[i]); il.Emit(OpCodes.Callvirt, propertyInfo.GetGetMethod()); // stack_0 = stack_0.Property SubserviceDescription subserviceDescription; if (!serviceDesc.TryGetSubservice(servicePath[i], out subserviceDescription)) { throw new InvalidPathException(); } serviceDesc = subserviceDescription.Service; } var methodName = servicePath.MethodName; MethodDescription methodDesc; if (!serviceDesc.TryGetMethod(methodName, out methodDesc)) { throw new InvalidPathException(); } bool hasRetval = methodDesc.ReturnType != typeof(void); var parameters = methodDesc.Parameters.Select((x, i) => new ParameterNecessity { Description = x, Codec = codecContainer.GetEmittingCodecFor(x.Type), LocalVariable = x.Way != MethodParameterWay.Val ? il.DeclareLocal(x.Type) : null, ArgumentIndex = i }) .ToArray(); var requestParameters = parameters .Where(x => x.Description.Way == MethodParameterWay.Val || x.Description.Way == MethodParameterWay.Ref) .ToArray(); var responseParameters = parameters .Where(x => x.Description.Way == MethodParameterWay.Ref || x.Description.Way == MethodParameterWay.Out) .ToArray(); LocalBuilder requestDataPointerVar = null; if (requestParameters.Any()) { il.Emit(OpCodes.Ldarg_1); // remainingBytes = arg_1.Length il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Stloc, locals.RemainingBytes); requestDataPointerVar = // var pinned dataPointer = pin(arg_1) il.Emit_PinArray(typeof(byte), 1); il.Emit(OpCodes.Ldloc, requestDataPointerVar); // data = dataPointer il.Emit(OpCodes.Stloc, locals.DataPointer); } foreach (var parameter in parameters) { switch (parameter.Description.Way) { case MethodParameterWay.Val: parameter.Codec.EmitDecode(il, locals, false); // stack_i = decode(data, remainingBytes, false) break; case MethodParameterWay.Ref: parameter.Codec.EmitDecode(il, locals, false); // param_i = decode(data, remainingBytes, false) il.Emit(OpCodes.Stloc, parameter.LocalVariable); il.Emit(OpCodes.Ldloca, parameter.LocalVariable); // stack_i = *param_i break; case MethodParameterWay.Out: il.Emit(OpCodes.Ldloca, parameter.LocalVariable); // stack_i = *param_i break; default: throw new ArgumentOutOfRangeException(); } } if (requestParameters.Any()) { il.Emit_UnpinArray(requestDataPointerVar); // unpin(dataPointer) } il.Emit(OpCodes.Callvirt, methodDesc.MethodInfo); // stack_0 = stack_0.Method(stack_1, stack_2, ...) if (hasRetval || responseParameters.Any()) { IEmittingCodec retvalCodec = null; LocalBuilder retvalVar = null; if (hasRetval) { retvalCodec = codecContainer.GetEmittingCodecFor(methodDesc.ReturnType); retvalVar = il.DeclareLocal(methodDesc.ReturnType); // var ret = stack_0 il.Emit(OpCodes.Stloc, retvalVar); retvalCodec.EmitCalculateSize(il, retvalVar); // stack_0 = calculateSize(ret) } bool hasSizeOnStack = hasRetval; foreach (var parameter in responseParameters) { parameter.Codec.EmitCalculateSize(il, parameter.LocalVariable); // stack_0 += calculateSize(param_i) if (hasSizeOnStack) { il.Emit(OpCodes.Add); } else { hasSizeOnStack = true; } } var dataArrayVar = il.DeclareLocal(typeof(byte[])); // var dataArray = new byte[size of retval] il.Emit(OpCodes.Newarr, typeof(byte)); il.Emit(OpCodes.Stloc, dataArrayVar); var responseDataPointerVar = // var pinned dataPointer = pin(dataArrayVar) il.Emit_PinArray(typeof(byte), dataArrayVar); il.Emit(OpCodes.Ldloc, responseDataPointerVar); // data = dataPointer il.Emit(OpCodes.Stloc, locals.DataPointer); foreach (var parameter in responseParameters) { parameter.Codec.EmitEncode(il, locals, parameter.LocalVariable);// encode(data, param_i) } if (hasRetval) { retvalCodec.EmitEncode(il, locals, retvalVar); // encode(data, ret) } il.Emit_UnpinArray(responseDataPointerVar); // unpin(dataPointer) il.Emit(OpCodes.Ldloc, dataArrayVar); // stack_0 = dataArray } else { il.Emit(OpCodes.Ldc_I4, 0); // stack_0 = new byte[0] il.Emit(OpCodes.Newarr, typeof(byte)); } il.Emit(OpCodes.Ret); return((ServiceMethodHandler)dynamicMethod.CreateDelegate(typeof(ServiceMethodHandler))); }
public void EmitEncode(IEmittingContext emittingContext) { typeCodec.EmitEncode(emittingContext, Loaders.TypeOf(type)); }
public void EmitEncode() { codec.EmitEncode(emittingContext, Loaders.Local(local)); }
public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, LocalBuilder localVar) { codec.EmitEncode(il, locals, lil => lil.Emit(OpCodes.Ldloc, localVar)); }
public static void EmitEncodeIndirect(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, int argIndex, Type type) { codec.EmitEncode(il, locals, lil => { lil.Emit_Ldarg(argIndex); lil.Emit(OpCodes.Ldobj, type); }); }
public static void EmitEncode(this IEmittingCodec codec, ILGenerator il, ILocalVariableCollection locals, int argIndex) { codec.EmitEncode(il, locals, lil => lil.Emit_Ldarg(argIndex)); }