protected override void CountSizeNotEmpty(SizeCounterMethodBuilderContext context) { int[] values; ulong[] hashCodes; EnumHelpers.BuildHashCodesTable(Type, out values, out hashCodes); var hashCodesField = context.Context.InitConstField(Type, 0, hashCodes); var valuesField = context.Context.InitConstField(Type, 1, values); var il = context.Il; context.LoadField(valuesField); // stack: [values] context.LoadObj(); // stack: [values, obj] il.Ldc_I4(values.Length); // stack: [values, obj, values.Length] il.Rem(true); // stack: [values, obj % values.Length] il.Ldelem(typeof(int)); // stack: [values[obj % values.Length]] context.LoadObj(); // stack: [values[obj % values.Length], obj] il.Ceq(); // stack: [values[obj % values.Length] == obj] var countAsIntLabel = il.DefineLabel("countAsInt"); il.Brfalse(countAsIntLabel); // if(values[obj % values.Length] != obj) goto countAsInt context.LoadField(hashCodesField); // stack: [hashCodes] context.LoadObj(); // stack: [hashCodes, obj] il.Ldc_I4(hashCodes.Length); // stack: [hashCodes, obj, hashCodes.Length] il.Rem(true); // stack: [hashCodes, obj % hashCodes.Length] il.Ldelem(typeof(long)); // stack: [hashCodes[obj % hashCodes.Length] = hashCode] il.Brfalse(countAsIntLabel); // if(hashCode == 0) goto countAsInt; il.Ldc_I4(9); // stack: [9] il.Ret(); // return 9; il.MarkLabel(countAsIntLabel); il.Ldc_I4(5); // stack: [5] }
protected override void WriteNotEmpty(WriterMethodBuilderContext context) { int[] values; ulong[] hashCodes; EnumHelpers.BuildHashCodesTable(Type, out values, out hashCodes); var hashCodesField = context.Context.InitConstField(Type, 0, hashCodes); var valuesField = context.Context.InitConstField(Type, 1, values); var il = context.Il; context.LoadField(valuesField); // stack: [values] context.LoadObj(); // stack: [values, obj] il.Ldc_I4(values.Length); // stack: [values, obj, values.Length] il.Rem(true); // stack: [values, obj % values.Length] il.Ldelem(typeof(int)); // stack: [values[obj % values.Length]] context.LoadObj(); // stack: [values[obj % values.Length], obj] il.Ceq(); // stack: [values[obj % values.Length] == obj] var writeIntLabel = il.DefineLabel("writeInt"); il.Brfalse(writeIntLabel); // if(values[obj % values.Length] != obj) goto writeInt context.LoadField(hashCodesField); // stack: [hashCodes] context.LoadObj(); // stack: [hashCodes, obj] il.Ldc_I4(hashCodes.Length); // stack: [hashCodes, obj, hashCodes.Length] il.Rem(true); // stack: [hashCodes, obj % hashCodes.Length] il.Ldelem(typeof(long)); // stack: [hashCodes[obj % hashCodes.Length] = hashCode] var hashCode = il.DeclareLocal(typeof(ulong)); il.Dup(); // stack: [hashCode, hashCode] il.Stloc(hashCode); // hashCode = hashCodes[obj % hashCodes.Length]; stack: [hashCode] il.Brfalse(writeIntLabel); context.WriteTypeCode(GroBufTypeCode.Enum); il.Ldc_I4(8); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&result[index]] il.Ldloc(hashCode); // stack: [&result[index], hashCode] il.Stind(typeof(long)); // *(int64*)&result[index] = hashCode context.IncreaseIndexBy8(); // index = index + 8; il.Ret(); il.MarkLabel(writeIntLabel); context.WriteTypeCode(GroBufTypeCode.Int32); il.Ldc_I4(4); context.AssertLength(); context.GoToCurrentLocation(); // stack: [&result[index]] context.LoadObj(); // stack: [&result[index], obj] il.Stind(typeof(int)); // result[index] = obj context.IncreaseIndexBy4(); // index = index + 4 }