Beispiel #1
0
        public static void EmitPackCode(Type type, MethodInfo mi, ILGenerator il,
			Func<Type,MemberInfo[]> targetMemberSelector,
			Func<MemberInfo,string> memberNameFormatter,
			Func<Type, MethodInfo> lookupPackMethod)
        {
            if ((type.IsPrimitive || type.IsInterface) && !type.IsMap())
                throw new NotSupportedException ();

            Variable arg_writer = Variable.CreateArg (0);
            Variable arg_obj = Variable.CreateArg (1);

            if (!type.IsValueType) { // null check
                Label notNullLabel = il.DefineLabel ();
                il.EmitLd (arg_obj);
                il.Emit (OpCodes.Brtrue_S, notNullLabel);
                il.EmitLd (arg_writer);
                il.Emit (OpCodes.Call, typeof(MsgPackWriter).GetMethod("WriteNil", new Type[0]));
                il.Emit (OpCodes.Ret);
                il.MarkLabel (notNullLabel);
            }

            if (type.IsArray)
            {
                EmitPackArrayCode(mi, il, type, arg_writer, arg_obj, Variable.CreateLocal(il.DeclareLocal(typeof(int))), lookupPackMethod);
                goto FinallyProcess;
            }
            if (type.IsMap())
            {
                //EmitPackDictCode(mi, il, type, arg_writer, arg_obj, lookupPackMethod);
                Compiler.DictionaryILGenerator.EmitPackIL(mi, il, type, arg_writer, arg_obj, lookupPackMethod);
                goto FinallyProcess;
            }
            // MsgPackWriter.WriteMapHeader
            MemberInfo[] members = targetMemberSelector(type);
            il.EmitLd(arg_writer);
            il.EmitLdc(members.Length);
            il.Emit(OpCodes.Callvirt, typeof(MsgPackWriter).GetMethod("WriteMapHeader", new Type[] { typeof(int) }));

            for (int i = 0; i < members.Length; i++)
            {
                MemberInfo m = members[i];
                Type mt = m.GetMemberType();

                // write field-name
                il.EmitLd(arg_writer);
                il.EmitLdstr(memberNameFormatter(m));
                il.EmitLd_True();
                il.Emit(OpCodes.Call, typeof(MsgPackWriter).GetMethod("Write", new Type[] { typeof(string), typeof(bool) }));

                // write value
                EmitPackMemberValueCode(mt, il, arg_writer, arg_obj, m, null, type, mi, lookupPackMethod);
            }

            FinallyProcess:
            il.Emit (OpCodes.Ret);
        }
Beispiel #2
0
		static void EmitPackArrayCode (MethodInfo mi, ILGenerator il, Type t, Variable var_writer, Variable var_obj, Variable var_loop, Func<Type, MethodInfo> lookupPackMethod)
		{
			Type et = t.GetElementType ();
			il.EmitLd (var_writer, var_obj);
			il.Emit (OpCodes.Ldlen);
			il.Emit (OpCodes.Call, typeof(MsgPackWriter).GetMethod("WriteArrayHeader", new Type[]{ typeof(int) }));

			Label beginLabel = il.DefineLabel ();
			Label exprLabel = il.DefineLabel ();

			// for-loop: init loop counter
			il.EmitLdc (0);
			il.EmitSt (var_loop);

			// jump
			il.Emit (OpCodes.Br_S, exprLabel);

			// mark begin-label
			il.MarkLabel (beginLabel);

			// write element
			EmitPackMemberValueCode (et, il, var_writer, var_obj, null, var_loop, t, mi, lookupPackMethod);

			// increment loop-counter
			il.EmitLd (var_loop);
			il.Emit (OpCodes.Ldc_I4_1);
			il.Emit (OpCodes.Add);
			il.EmitSt (var_loop);

			// mark expression label
			il.MarkLabel (exprLabel);

			// expression
			il.EmitLd (var_loop, var_obj);
			il.Emit (OpCodes.Ldlen);
			il.Emit (OpCodes.Blt_S, beginLabel);
		}
Beispiel #3
0
		static void EmitUnpackReadAndTypeCheckCode (ILGenerator il, Variable msgpackReader, MethodInfo typeCheckMethod, MethodInfo failedMethod, bool nullCheckAndReturn)
		{
			Label lblFailed = il.DefineLabel ();
			Label lblNullReturn = nullCheckAndReturn ? il.DefineLabel () : default(Label);
			Label lblPassed = il.DefineLabel ();
			il.EmitLd (msgpackReader);
			il.Emit (OpCodes.Call, typeof (MsgPackReader).GetMethod ("Read"));
			il.Emit (OpCodes.Brfalse_S, lblFailed);
			if (nullCheckAndReturn) {
				il.EmitLd (msgpackReader);
				il.Emit (OpCodes.Call, typeof (MsgPackReader).GetProperty ("Type").GetGetMethod ());
				il.EmitLdc ((int)TypePrefixes.Nil);
				il.Emit (OpCodes.Beq_S, lblNullReturn);
			}
			il.EmitLd (msgpackReader);
			il.Emit (OpCodes.Call, typeCheckMethod);
			il.Emit (OpCodes.Brtrue_S, lblPassed);
			il.Emit (OpCodes.Br, lblFailed);
			if (nullCheckAndReturn) {
				il.MarkLabel (lblNullReturn);
				il.Emit (OpCodes.Ldnull);
				il.Emit (OpCodes.Ret);
			}
			il.MarkLabel (lblFailed);
			il.Emit (OpCodes.Call, failedMethod);
			il.MarkLabel (lblPassed);
		}
Beispiel #4
0
		static void EmitUnpackArrayCode (Type arrayType, MethodInfo mi, ILGenerator il,
			Func<Type,MemberInfo[]> targetMemberSelector,
			Func<MemberInfo,string> memberNameFormatter,
			Func<Type, MethodInfo> lookupUnpackMethod)
		{
			Type elementType = arrayType.GetElementType ();
			MethodInfo failedMethod = typeof (PackILGenerator).GetMethod ("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic);

			Variable msgpackReader = Variable.CreateArg (0);
			Variable obj = Variable.CreateLocal (il.DeclareLocal (arrayType));
			Variable num_of_elements = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
			Variable loop_idx = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
			Variable type = Variable.CreateLocal (il.DeclareLocal (typeof (Type)));

			// if (!MsgPackReader.Read() || !MsgPackReader.IsArray ()) UnpackFailed ();
			EmitUnpackReadAndTypeCheckCode (il, msgpackReader, typeof (MsgPackReader).GetMethod ("IsArray"), failedMethod, true);

			// type = typeof (T)
			il.Emit (OpCodes.Ldtoken, elementType);
			il.Emit (OpCodes.Call, typeof(Type).GetMethod ("GetTypeFromHandle"));
			il.EmitSt (type);

			// num_of_elements = (int)reader.Length
			il.EmitLd (msgpackReader);
			il.Emit (OpCodes.Call, typeof (MsgPackReader).GetProperty ("Length").GetGetMethod ());
			il.EmitSt (num_of_elements);

			// object o = Array.CreateInstance (Type, Length);
			il.EmitLd (type);
			il.EmitLd (num_of_elements);
			il.Emit (OpCodes.Call, typeof (Array).GetMethod ("CreateInstance", new Type[] {typeof (Type), typeof (int)}));
			il.Emit (OpCodes.Castclass, arrayType);
			il.EmitSt (obj);

			// Unpack element method
			MethodInfo unpack_method = lookupUnpackMethod (elementType);

			// Loop labels
			Label lblLoopStart = il.DefineLabel ();
			Label lblLoopExpr = il.DefineLabel ();
			
			// i = 0;
			il.EmitLdc (0);
			il.EmitSt (loop_idx);
			il.Emit (OpCodes.Br, lblLoopExpr);
			il.MarkLabel (lblLoopStart);

			/* process */
			il.EmitLd (obj, loop_idx);
			il.EmitLd (msgpackReader);
			il.Emit (OpCodes.Call, unpack_method);
			il.Emit (OpCodes.Stelem, elementType);

			// i ++
			il.EmitLd (loop_idx);
			il.EmitLdc (1);
			il.Emit (OpCodes.Add);
			il.EmitSt (loop_idx);

			// i < num_of_fields;
			il.MarkLabel (lblLoopExpr);
			il.EmitLd (loop_idx);
			il.EmitLd (num_of_elements);
			il.Emit (OpCodes.Blt, lblLoopStart);
			
			// return
			il.EmitLd (obj);
			il.Emit (OpCodes.Ret);
		}
Beispiel #5
0
		static void EmitUnpackMapCode (Type type, MethodInfo mi, ILGenerator il,
			Func<Type,MemberInfo[]> targetMemberSelector,
			Func<MemberInfo,string> memberNameFormatter,
			Func<Type, MethodInfo> lookupUnpackMethod,
			Func<Type, IDictionary<string,int>> lookupMemberMapping,
			MethodInfo lookupMemberMappingMethod)
		{
			MethodInfo failedMethod = typeof (PackILGenerator).GetMethod ("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic);
			MemberInfo[] members = targetMemberSelector (type);
			IDictionary<string, int> member_mapping = lookupMemberMapping (type);
			for (int i = 0; i < members.Length; i ++)
				member_mapping.Add (memberNameFormatter (members[i]), i);

			Variable msgpackReader = Variable.CreateArg (0);
			Variable obj = Variable.CreateLocal (il.DeclareLocal (type));
			Variable num_of_fields = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
			Variable loop_idx = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
			Variable mapping = Variable.CreateLocal (il.DeclareLocal (typeof (IDictionary<string, int>)));
			Variable switch_idx = Variable.CreateLocal (il.DeclareLocal (typeof (int)));
			Variable var_type = Variable.CreateLocal (il.DeclareLocal (typeof (Type)));

			// if (!MsgPackReader.Read()) UnpackFailed ();
			// if (MsgPackReader.Type == TypePrefixes.Nil) return null;
			// if (!MsgPackReader.IsMap ()) UnpackFailed ();
			EmitUnpackReadAndTypeCheckCode (il, msgpackReader, typeof (MsgPackReader).GetMethod ("IsMap"), failedMethod, true);
			
			// type = typeof (T)
			il.Emit (OpCodes.Ldtoken, type);
			il.Emit (OpCodes.Call, typeof(Type).GetMethod ("GetTypeFromHandle"));
			il.EmitSt (var_type);

			// mapping = LookupMemberMapping (typeof (T))
			il.EmitLd (var_type);
			il.Emit (OpCodes.Call, lookupMemberMappingMethod);
			il.EmitSt (mapping);

			// object o = FormatterServices.GetUninitializedObject (Type);
			il.EmitLd (var_type);
			il.Emit (OpCodes.Call, typeof (FormatterServices).GetMethod ("GetUninitializedObject"));
			il.Emit (OpCodes.Castclass, type);
			il.EmitSt (obj);

			// num_of_fields = (int)reader.Length
			il.EmitLd (msgpackReader);
			il.Emit (OpCodes.Call, typeof (MsgPackReader).GetProperty ("Length").GetGetMethod ());
			il.EmitSt (num_of_fields);

			// Loop labels
			Label lblLoopStart = il.DefineLabel ();
			Label lblLoopExpr = il.DefineLabel ();
			
			// i = 0;
			il.EmitLdc (0);
			il.EmitSt (loop_idx);
			il.Emit (OpCodes.Br, lblLoopExpr);
			il.MarkLabel (lblLoopStart);

			/* process */
			// if (!MsgPackReader.Read() || !MsgPackReader.IsRaw()) UnpackFailed();
			EmitUnpackReadAndTypeCheckCode (il, msgpackReader, typeof (MsgPackReader).GetMethod ("IsRaw"), failedMethod, false);

			// MsgPackReader.ReadRawString ()
			// if (!Dictionary.TryGetValue (,)) UnpackFailed();
			Label lbl3 = il.DefineLabel ();
			il.EmitLd (mapping);
			il.EmitLd (msgpackReader);
			il.Emit (OpCodes.Call, typeof (MsgPackReader).GetMethod ("ReadRawString", new Type[0]));
			il.Emit (OpCodes.Ldloca_S, (byte)switch_idx.Index);
			il.Emit (OpCodes.Callvirt, typeof (IDictionary<string,int>).GetMethod ("TryGetValue"));
			il.Emit (OpCodes.Brtrue, lbl3);
			il.Emit (OpCodes.Call, failedMethod);
			il.MarkLabel (lbl3);

			// switch
			Label[] switchCases = new Label[members.Length];
			for (int i = 0; i < switchCases.Length; i ++)
				switchCases[i] = il.DefineLabel ();
			Label switchCaseEndLabel = il.DefineLabel ();
			il.EmitLd (switch_idx);
			il.Emit (OpCodes.Switch, switchCases);
			il.Emit (OpCodes.Call, failedMethod);

			for (int i = 0; i < switchCases.Length; i ++) {
				il.MarkLabel (switchCases[i]);
				MemberInfo minfo = members[i];
				Type mt = minfo.GetMemberType ();
				MethodInfo unpack_method = lookupUnpackMethod (mt);
				il.EmitLd (obj);
				il.EmitLd (msgpackReader);
				il.Emit (OpCodes.Call, unpack_method);
				il.EmitStMember (minfo);
				il.Emit (OpCodes.Br, switchCaseEndLabel);
			}
			il.MarkLabel (switchCaseEndLabel);

			// i ++
			il.EmitLd (loop_idx);
			il.EmitLdc (1);
			il.Emit (OpCodes.Add);
			il.EmitSt (loop_idx);

			// i < num_of_fields;
			il.MarkLabel (lblLoopExpr);
			il.EmitLd (loop_idx);
			il.EmitLd (num_of_fields);
			il.Emit (OpCodes.Blt, lblLoopStart);
			
			// return
			il.EmitLd (obj);
			il.Emit (OpCodes.Ret);
		}