Commit f1ad61c7 authored by Joseph Musser's avatar Joseph Musser Committed by Marc Gravell

Use LocalBuilders rather than hardcoding or passing local indexes (#1282)

* Pass LocalBuilders instead of indexes since ILGenerator already optimizes the opcode used

* Eradicate magic local indexes to make refactoring safer
parent 6754fe27
...@@ -2391,19 +2391,21 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2391,19 +2391,21 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
var il = dm.GetILGenerator(); var il = dm.GetILGenerator();
bool isStruct = type.IsValueType(); bool isStruct = type.IsValueType();
bool haveInt32Arg1 = false; var sizeLocal = (LocalBuilder)null;
il.Emit(OpCodes.Ldarg_1); // stack is now [untyped-param] il.Emit(OpCodes.Ldarg_1); // stack is now [untyped-param]
LocalBuilder typedParameterLocal;
if (isStruct) if (isStruct)
{ {
il.DeclareLocal(type.MakeByRefType()); // note: ref-local typedParameterLocal = il.DeclareLocal(type.MakeByRefType()); // note: ref-local
il.Emit(OpCodes.Unbox, type); // stack is now [typed-param] il.Emit(OpCodes.Unbox, type); // stack is now [typed-param]
} }
else else
{ {
il.DeclareLocal(type); // 0 typedParameterLocal = il.DeclareLocal(type);
il.Emit(OpCodes.Castclass, type); // stack is now [typed-param] il.Emit(OpCodes.Castclass, type); // stack is now [typed-param]
} }
il.Emit(OpCodes.Stloc_0);// stack is now empty il.Emit(OpCodes.Stloc, typedParameterLocal); // stack is now empty
il.Emit(OpCodes.Ldarg_0); // stack is now [command] il.Emit(OpCodes.Ldarg_0); // stack is now [command]
il.EmitCall(OpCodes.Callvirt, typeof(IDbCommand).GetProperty(nameof(IDbCommand.Parameters)).GetGetMethod(), null); // stack is now [parameters] il.EmitCall(OpCodes.Callvirt, typeof(IDbCommand).GetProperty(nameof(IDbCommand.Parameters)).GetGetMethod(), null); // stack is now [parameters]
...@@ -2482,7 +2484,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2482,7 +2484,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
{ {
if (typeof(ICustomQueryParameter).IsAssignableFrom(prop.PropertyType)) if (typeof(ICustomQueryParameter).IsAssignableFrom(prop.PropertyType))
{ {
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [typed-param] il.Emit(OpCodes.Ldloc, typedParameterLocal); // stack is now [parameters] [typed-param]
il.Emit(callOpCode, prop.GetGetMethod()); // stack is [parameters] [custom] il.Emit(callOpCode, prop.GetGetMethod()); // stack is [parameters] [custom]
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [custom] [command] il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [custom] [command]
il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [custom] [command] [name] il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [custom] [command] [name]
...@@ -2497,7 +2499,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2497,7 +2499,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
// this actually represents special handling for list types; // this actually represents special handling for list types;
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [command] il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [command]
il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [command] [name] il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [command] [name]
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [command] [name] [typed-param] il.Emit(OpCodes.Ldloc, typedParameterLocal); // stack is now [parameters] [command] [name] [typed-param]
il.Emit(callOpCode, prop.GetGetMethod()); // stack is [parameters] [command] [name] [typed-value] il.Emit(callOpCode, prop.GetGetMethod()); // stack is [parameters] [command] [name] [typed-value]
if (prop.PropertyType.IsValueType()) if (prop.PropertyType.IsValueType())
{ {
...@@ -2531,7 +2533,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2531,7 +2533,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
if (dbType == DbType.Object && prop.PropertyType == typeof(object)) // includes dynamic if (dbType == DbType.Object && prop.PropertyType == typeof(object)) // includes dynamic
{ {
// look it up from the param value // look it up from the param value
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [[parameters]] [parameter] [parameter] [typed-param] il.Emit(OpCodes.Ldloc, typedParameterLocal); // stack is now [parameters] [[parameters]] [parameter] [parameter] [typed-param]
il.Emit(callOpCode, prop.GetGetMethod()); // stack is [parameters] [[parameters]] [parameter] [parameter] [object-value] il.Emit(callOpCode, prop.GetGetMethod()); // stack is [parameters] [[parameters]] [parameter] [parameter] [object-value]
il.Emit(OpCodes.Call, typeof(SqlMapper).GetMethod(nameof(SqlMapper.GetDbType), BindingFlags.Static | BindingFlags.Public)); // stack is now [parameters] [[parameters]] [parameter] [parameter] [db-type] il.Emit(OpCodes.Call, typeof(SqlMapper).GetMethod(nameof(SqlMapper.GetDbType), BindingFlags.Static | BindingFlags.Public)); // stack is now [parameters] [[parameters]] [parameter] [parameter] [db-type]
} }
...@@ -2548,7 +2550,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2548,7 +2550,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Direction)).GetSetMethod(), null);// stack is now [parameters] [[parameters]] [parameter] il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty(nameof(IDataParameter.Direction)).GetSetMethod(), null);// stack is now [parameters] [[parameters]] [parameter]
il.Emit(OpCodes.Dup);// stack is now [parameters] [[parameters]] [parameter] [parameter] il.Emit(OpCodes.Dup);// stack is now [parameters] [[parameters]] [parameter] [parameter]
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [[parameters]] [parameter] [parameter] [typed-param] il.Emit(OpCodes.Ldloc, typedParameterLocal); // stack is now [parameters] [[parameters]] [parameter] [parameter] [typed-param]
il.Emit(callOpCode, prop.GetGetMethod()); // stack is [parameters] [[parameters]] [parameter] [parameter] [typed-value] il.Emit(callOpCode, prop.GetGetMethod()); // stack is [parameters] [[parameters]] [parameter] [parameter] [typed-value]
bool checkForNull; bool checkForNull;
if (prop.PropertyType.IsValueType()) if (prop.PropertyType.IsValueType())
...@@ -2600,10 +2602,9 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2600,10 +2602,9 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
} }
if (checkForNull) if (checkForNull)
{ {
if ((dbType == DbType.String || dbType == DbType.AnsiString) && !haveInt32Arg1) if ((dbType == DbType.String || dbType == DbType.AnsiString) && sizeLocal == null)
{ {
il.DeclareLocal(typeof(int)); sizeLocal = il.DeclareLocal(typeof(int));
haveInt32Arg1 = true;
} }
// relative stack: [boxed value] // relative stack: [boxed value]
il.Emit(OpCodes.Dup);// relative stack: [boxed value] [boxed value] il.Emit(OpCodes.Dup);// relative stack: [boxed value] [boxed value]
...@@ -2616,7 +2617,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2616,7 +2617,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
if (dbType == DbType.String || dbType == DbType.AnsiString) if (dbType == DbType.String || dbType == DbType.AnsiString)
{ {
EmitInt32(il, 0); EmitInt32(il, 0);
il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Stloc, sizeLocal);
} }
if (allDone != null) il.Emit(OpCodes.Br_S, allDone.Value); if (allDone != null) il.Emit(OpCodes.Br_S, allDone.Value);
il.MarkLabel(notNull); il.MarkLabel(notNull);
...@@ -2633,7 +2634,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2633,7 +2634,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
il.MarkLabel(isLong); il.MarkLabel(isLong);
EmitInt32(il, -1); // [string] [-1] EmitInt32(il, -1); // [string] [-1]
il.MarkLabel(lenDone); il.MarkLabel(lenDone);
il.Emit(OpCodes.Stloc_1); // [string] il.Emit(OpCodes.Stloc, sizeLocal); // [string]
} }
if (prop.PropertyType.FullName == LinqBinary) if (prop.PropertyType.FullName == LinqBinary)
{ {
...@@ -2658,11 +2659,11 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2658,11 +2659,11 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
{ {
var endOfSize = il.DefineLabel(); var endOfSize = il.DefineLabel();
// don't set if 0 // don't set if 0
il.Emit(OpCodes.Ldloc_1); // [parameters] [[parameters]] [parameter] [size] il.Emit(OpCodes.Ldloc, sizeLocal); // [parameters] [[parameters]] [parameter] [size]
il.Emit(OpCodes.Brfalse_S, endOfSize); // [parameters] [[parameters]] [parameter] il.Emit(OpCodes.Brfalse_S, endOfSize); // [parameters] [[parameters]] [parameter]
il.Emit(OpCodes.Dup);// stack is now [parameters] [[parameters]] [parameter] [parameter] il.Emit(OpCodes.Dup);// stack is now [parameters] [[parameters]] [parameter] [parameter]
il.Emit(OpCodes.Ldloc_1); // stack is now [parameters] [[parameters]] [parameter] [parameter] [size] il.Emit(OpCodes.Ldloc, sizeLocal); // stack is now [parameters] [[parameters]] [parameter] [parameter] [size]
il.EmitCall(OpCodes.Callvirt, typeof(IDbDataParameter).GetProperty(nameof(IDbDataParameter.Size)).GetSetMethod(), null); // stack is now [parameters] [[parameters]] [parameter] il.EmitCall(OpCodes.Callvirt, typeof(IDbDataParameter).GetProperty(nameof(IDbDataParameter.Size)).GetSetMethod(), null); // stack is now [parameters] [[parameters]] [parameter]
il.MarkLabel(endOfSize); il.MarkLabel(endOfSize);
...@@ -2715,7 +2716,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql) ...@@ -2715,7 +2716,7 @@ internal static IList<LiteralToken> GetLiteralTokens(string sql)
if (prop != null) if (prop != null)
{ {
il.Emit(OpCodes.Ldstr, literal.Token); il.Emit(OpCodes.Ldstr, literal.Token);
il.Emit(OpCodes.Ldloc_0); // command, sql, typed parameter il.Emit(OpCodes.Ldloc, typedParameterLocal); // command, sql, typed parameter
il.EmitCall(callOpCode, prop.GetGetMethod(), null); // command, sql, typed value il.EmitCall(callOpCode, prop.GetGetMethod(), null); // command, sql, typed value
Type propType = prop.PropertyType; Type propType = prop.PropertyType;
var typeCode = TypeExtensions.GetTypeCode(propType); var typeCode = TypeExtensions.GetTypeCode(propType);
...@@ -3046,9 +3047,9 @@ private static LocalBuilder GetTempLocal(ILGenerator il, ref Dictionary<Type, Lo ...@@ -3046,9 +3047,9 @@ private static LocalBuilder GetTempLocal(ILGenerator il, ref Dictionary<Type, Lo
} }
if (initAndLoad) if (initAndLoad)
{ {
il.Emit(OpCodes.Ldloca, (short)found.LocalIndex); il.Emit(OpCodes.Ldloca, found);
il.Emit(OpCodes.Initobj, type); il.Emit(OpCodes.Initobj, type);
il.Emit(OpCodes.Ldloca, (short)found.LocalIndex); il.Emit(OpCodes.Ldloca, found);
il.Emit(OpCodes.Ldobj, type); il.Emit(OpCodes.Ldobj, type);
} }
return found; return found;
...@@ -3135,7 +3136,7 @@ private static void GenerateValueTupleDeserializer(Type valueTupleType, IDataRea ...@@ -3135,7 +3136,7 @@ private static void GenerateValueTupleDeserializer(Type valueTupleType, IDataRea
} }
} }
var enumDeclareLocal = -1; var stringEnumLocal = (LocalBuilder)null;
for (var i = 0; i < languageTupleElementTypes.Count; i++) for (var i = 0; i < languageTupleElementTypes.Count; i++)
{ {
...@@ -3146,7 +3147,7 @@ private static void GenerateValueTupleDeserializer(Type valueTupleType, IDataRea ...@@ -3146,7 +3147,7 @@ private static void GenerateValueTupleDeserializer(Type valueTupleType, IDataRea
LoadReaderValueOrBranchToDBNullLabel( LoadReaderValueOrBranchToDBNullLabel(
il, il,
startBound + i, startBound + i,
ref enumDeclareLocal, ref stringEnumLocal,
valueCopyLocal: null, valueCopyLocal: null,
reader.GetFieldType(startBound + i), reader.GetFieldType(startBound + i),
targetType, targetType,
...@@ -3179,9 +3180,9 @@ private static void GenerateValueTupleDeserializer(Type valueTupleType, IDataRea ...@@ -3179,9 +3180,9 @@ private static void GenerateValueTupleDeserializer(Type valueTupleType, IDataRea
private static void GenerateDeserializerFromMap(Type type, IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing, ILGenerator il) private static void GenerateDeserializerFromMap(Type type, IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing, ILGenerator il)
{ {
var currentIndexDiagnosticLocal = il.DeclareLocal(typeof(int)); var currentIndexDiagnosticLocal = il.DeclareLocal(typeof(int));
il.DeclareLocal(type); var returnValueLocal = il.DeclareLocal(type);
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Stloc, currentIndexDiagnosticLocal);
var names = Enumerable.Range(startBound, length).Select(i => reader.GetName(i)).ToArray(); var names = Enumerable.Range(startBound, length).Select(i => reader.GetName(i)).ToArray();
...@@ -3196,7 +3197,7 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3196,7 +3197,7 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
Dictionary<Type, LocalBuilder> structLocals = null; Dictionary<Type, LocalBuilder> structLocals = null;
if (type.IsValueType()) if (type.IsValueType())
{ {
il.Emit(OpCodes.Ldloca_S, (byte)1); il.Emit(OpCodes.Ldloca, returnValueLocal);
il.Emit(OpCodes.Initobj, type); il.Emit(OpCodes.Initobj, type);
} }
else else
...@@ -3224,12 +3225,12 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3224,12 +3225,12 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
} }
il.Emit(OpCodes.Newobj, explicitConstr); il.Emit(OpCodes.Newobj, explicitConstr);
il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Stloc, returnValueLocal);
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
supportInitialize = typeof(ISupportInitialize).IsAssignableFrom(type); supportInitialize = typeof(ISupportInitialize).IsAssignableFrom(type);
if (supportInitialize) if (supportInitialize)
{ {
il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Ldloc, returnValueLocal);
il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.BeginInit)), null); il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.BeginInit)), null);
} }
#endif #endif
...@@ -3246,12 +3247,12 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3246,12 +3247,12 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
if (ctor.GetParameters().Length == 0) if (ctor.GetParameters().Length == 0)
{ {
il.Emit(OpCodes.Newobj, ctor); il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Stloc, returnValueLocal);
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
supportInitialize = typeof(ISupportInitialize).IsAssignableFrom(type); supportInitialize = typeof(ISupportInitialize).IsAssignableFrom(type);
if (supportInitialize) if (supportInitialize)
{ {
il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Ldloc, returnValueLocal);
il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.BeginInit)), null); il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.BeginInit)), null);
} }
#endif #endif
...@@ -3266,11 +3267,11 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3266,11 +3267,11 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
il.BeginExceptionBlock(); il.BeginExceptionBlock();
if (type.IsValueType()) if (type.IsValueType())
{ {
il.Emit(OpCodes.Ldloca_S, (byte)1);// [target] il.Emit(OpCodes.Ldloca, returnValueLocal); // [target]
} }
else if (specializedConstructor == null) else if (specializedConstructor == null)
{ {
il.Emit(OpCodes.Ldloc_1);// [target] il.Emit(OpCodes.Ldloc, returnValueLocal); // [target]
} }
var members = (specializedConstructor != null var members = (specializedConstructor != null
...@@ -3281,7 +3282,8 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3281,7 +3282,8 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
bool first = true; bool first = true;
var allDone = il.DefineLabel(); var allDone = il.DefineLabel();
int enumDeclareLocal = -1, valueCopyLocal = il.DeclareLocal(typeof(object)).LocalIndex; var stringEnumLocal = (LocalBuilder)null;
var valueCopyDiagnosticLocal = il.DeclareLocal(typeof(object));
bool applyNullSetting = Settings.ApplyNullValues; bool applyNullSetting = Settings.ApplyNullValues;
foreach (var item in members) foreach (var item in members)
{ {
...@@ -3296,7 +3298,7 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3296,7 +3298,7 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
EmitInt32(il, index); EmitInt32(il, index);
il.Emit(OpCodes.Stloc, currentIndexDiagnosticLocal); il.Emit(OpCodes.Stloc, currentIndexDiagnosticLocal);
LoadReaderValueOrBranchToDBNullLabel(il, index, ref enumDeclareLocal, valueCopyLocal, reader.GetFieldType(index), memberType, out var isDbNullLabel); LoadReaderValueOrBranchToDBNullLabel(il, index, ref stringEnumLocal, valueCopyDiagnosticLocal, reader.GetFieldType(index), memberType, out var isDbNullLabel);
if (specializedConstructor == null) if (specializedConstructor == null)
{ {
...@@ -3353,7 +3355,7 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3353,7 +3355,7 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
{ {
il.Emit(OpCodes.Pop); il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldnull); // stack is now [null] il.Emit(OpCodes.Ldnull); // stack is now [null]
il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Stloc, returnValueLocal);
il.Emit(OpCodes.Br, allDone); il.Emit(OpCodes.Br, allDone);
} }
...@@ -3372,11 +3374,11 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3372,11 +3374,11 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
{ {
il.Emit(OpCodes.Newobj, specializedConstructor); il.Emit(OpCodes.Newobj, specializedConstructor);
} }
il.Emit(OpCodes.Stloc_1); // stack is empty il.Emit(OpCodes.Stloc, returnValueLocal); // stack is empty
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
if (supportInitialize) if (supportInitialize)
{ {
il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Ldloc, returnValueLocal);
il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.EndInit)), null); il.EmitCall(OpCodes.Callvirt, typeof(ISupportInitialize).GetMethod(nameof(ISupportInitialize.EndInit)), null);
} }
#endif #endif
...@@ -3385,11 +3387,11 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i ...@@ -3385,11 +3387,11 @@ private static void GenerateDeserializerFromMap(Type type, IDataReader reader, i
il.BeginCatchBlock(typeof(Exception)); // stack is Exception il.BeginCatchBlock(typeof(Exception)); // stack is Exception
il.Emit(OpCodes.Ldloc, currentIndexDiagnosticLocal); // stack is Exception, index il.Emit(OpCodes.Ldloc, currentIndexDiagnosticLocal); // stack is Exception, index
il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader
LoadLocal(il, valueCopyLocal); // stack is Exception, index, reader, value il.Emit(OpCodes.Ldloc, valueCopyDiagnosticLocal); // stack is Exception, index, reader, value
il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod(nameof(SqlMapper.ThrowDataException)), null); il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod(nameof(SqlMapper.ThrowDataException)), null);
il.EndExceptionBlock(); il.EndExceptionBlock();
il.Emit(OpCodes.Ldloc_1); // stack is [rval] il.Emit(OpCodes.Ldloc, returnValueLocal); // stack is [rval]
if (type.IsValueType()) if (type.IsValueType())
{ {
il.Emit(OpCodes.Box, type); il.Emit(OpCodes.Box, type);
...@@ -3401,10 +3403,10 @@ private static void LoadDefaultValue(ILGenerator il, Type type) ...@@ -3401,10 +3403,10 @@ private static void LoadDefaultValue(ILGenerator il, Type type)
{ {
if (type.IsValueType()) if (type.IsValueType())
{ {
int localIndex = il.DeclareLocal(type).LocalIndex; var local = il.DeclareLocal(type);
LoadLocalAddress(il, localIndex); il.Emit(OpCodes.Ldloca, local);
il.Emit(OpCodes.Initobj, type); il.Emit(OpCodes.Initobj, type);
LoadLocal(il, localIndex); il.Emit(OpCodes.Ldloc, local);
} }
else else
{ {
...@@ -3412,7 +3414,7 @@ private static void LoadDefaultValue(ILGenerator il, Type type) ...@@ -3412,7 +3414,7 @@ private static void LoadDefaultValue(ILGenerator il, Type type)
} }
} }
private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int index, ref int enumDeclareLocal, int? valueCopyLocal, Type colType, Type memberType, out Label isDbNullLabel) private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int index, ref LocalBuilder stringEnumLocal, LocalBuilder valueCopyLocal, Type colType, Type memberType, out Label isDbNullLabel)
{ {
isDbNullLabel = il.DefineLabel(); isDbNullLabel = il.DefineLabel();
il.Emit(OpCodes.Ldarg_0); // stack is now [...][reader] il.Emit(OpCodes.Ldarg_0); // stack is now [...][reader]
...@@ -3422,7 +3424,7 @@ private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int ind ...@@ -3422,7 +3424,7 @@ private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int ind
if (valueCopyLocal != null) if (valueCopyLocal != null)
{ {
il.Emit(OpCodes.Dup); // stack is now [...][value-as-object][value-as-object] il.Emit(OpCodes.Dup); // stack is now [...][value-as-object][value-as-object]
StoreLocal(il, valueCopyLocal.Value); // stack is now [...][value-as-object] il.Emit(OpCodes.Stloc, valueCopyLocal); // stack is now [...][value-as-object]
} }
if (memberType == typeof(char) || memberType == typeof(char?)) if (memberType == typeof(char) || memberType == typeof(char?))
...@@ -3446,15 +3448,15 @@ private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int ind ...@@ -3446,15 +3448,15 @@ private static void LoadReaderValueOrBranchToDBNullLabel(ILGenerator il, int ind
Type numericType = Enum.GetUnderlyingType(unboxType); Type numericType = Enum.GetUnderlyingType(unboxType);
if (colType == typeof(string)) if (colType == typeof(string))
{ {
if (enumDeclareLocal == -1) if (stringEnumLocal == null)
{ {
enumDeclareLocal = il.DeclareLocal(typeof(string)).LocalIndex; stringEnumLocal = il.DeclareLocal(typeof(string));
} }
il.Emit(OpCodes.Castclass, typeof(string)); // stack is now [...][string] il.Emit(OpCodes.Castclass, typeof(string)); // stack is now [...][string]
StoreLocal(il, enumDeclareLocal); // stack is now [...] il.Emit(OpCodes.Stloc, stringEnumLocal); // stack is now [...]
il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [...][enum-type-token] il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [...][enum-type-token]
il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle)), null);// stack is now [...][enum-type] il.EmitCall(OpCodes.Call, typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle)), null);// stack is now [...][enum-type]
LoadLocal(il, enumDeclareLocal); // stack is now [...][enum-type][string] il.Emit(OpCodes.Ldloc, stringEnumLocal); // stack is now [...][enum-type][string]
il.Emit(OpCodes.Ldc_I4_1); // stack is now [...][enum-type][string][true] il.Emit(OpCodes.Ldc_I4_1); // stack is now [...][enum-type][string][true]
il.EmitCall(OpCodes.Call, enumParse, null); // stack is now [...][enum-as-object] il.EmitCall(OpCodes.Call, enumParse, null); // stack is now [...][enum-as-object]
il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [...][typed-value] il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [...][typed-value]
...@@ -3608,64 +3610,6 @@ private static MethodInfo ResolveOperator(MethodInfo[] methods, Type from, Type ...@@ -3608,64 +3610,6 @@ private static MethodInfo ResolveOperator(MethodInfo[] methods, Type from, Type
return null; return null;
} }
private static void LoadLocal(ILGenerator il, int index)
{
if (index < 0 || index >= short.MaxValue) throw new ArgumentNullException(nameof(index));
switch (index)
{
case 0: il.Emit(OpCodes.Ldloc_0); break;
case 1: il.Emit(OpCodes.Ldloc_1); break;
case 2: il.Emit(OpCodes.Ldloc_2); break;
case 3: il.Emit(OpCodes.Ldloc_3); break;
default:
if (index <= 255)
{
il.Emit(OpCodes.Ldloc_S, (byte)index);
}
else
{
il.Emit(OpCodes.Ldloc, (short)index);
}
break;
}
}
private static void StoreLocal(ILGenerator il, int index)
{
if (index < 0 || index >= short.MaxValue) throw new ArgumentNullException(nameof(index));
switch (index)
{
case 0: il.Emit(OpCodes.Stloc_0); break;
case 1: il.Emit(OpCodes.Stloc_1); break;
case 2: il.Emit(OpCodes.Stloc_2); break;
case 3: il.Emit(OpCodes.Stloc_3); break;
default:
if (index <= 255)
{
il.Emit(OpCodes.Stloc_S, (byte)index);
}
else
{
il.Emit(OpCodes.Stloc, (short)index);
}
break;
}
}
private static void LoadLocalAddress(ILGenerator il, int index)
{
if (index < 0 || index >= short.MaxValue) throw new ArgumentNullException(nameof(index));
if (index <= 255)
{
il.Emit(OpCodes.Ldloca_S, (byte)index);
}
else
{
il.Emit(OpCodes.Ldloca, (short)index);
}
}
/// <summary> /// <summary>
/// Throws a data exception, only used internally /// Throws a data exception, only used internally
/// </summary> /// </summary>
...@@ -3795,7 +3739,7 @@ public static void SetTypeName(this DataTable table, string typeName) ...@@ -3795,7 +3739,7 @@ public static void SetTypeName(this DataTable table, string typeName)
public static ICustomQueryParameter AsTableValuedParameter<T>(this IEnumerable<T> list, string typeName = null) where T : IDataRecord => public static ICustomQueryParameter AsTableValuedParameter<T>(this IEnumerable<T> list, string typeName = null) where T : IDataRecord =>
new SqlDataRecordListTVPParameter<T>(list, typeName); new SqlDataRecordListTVPParameter<T>(list, typeName);
/* /*
/// <summary> /// <summary>
/// Used to pass a IEnumerable&lt;SqlDataRecord&gt; as a TableValuedParameter. /// Used to pass a IEnumerable&lt;SqlDataRecord&gt; as a TableValuedParameter.
/// </summary> /// </summary>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment