void StoreCurrentPosition(IILGen ilGenerator, Action <IILGen> pushReader, IILLocal positionLoc) { ilGenerator .Do(pushReader) .Callvirt(() => default(ByteArrayReader).GetCurrentPosition()) .Stloc(positionLoc); }
static ushort SaveMethodParameters(IILGen ilGenerator, string methodName, ParameterInfo[] methodParameters, int paramCount, IDictionary <string, MethodInfo> apartFields, IEnumerable <TableFieldInfo> fields, IILLocal writerLoc) { ushort usedApartFieldsCount = 0; ushort idx = 0; foreach (var field in fields) { MethodInfo fieldGetter; if (apartFields.TryGetValue(field.Name, out fieldGetter)) { usedApartFieldsCount++; SaveKeyFieldFromApartField(ilGenerator, field, fieldGetter, writerLoc); continue; } if (idx == paramCount) { break; } var par = methodParameters[idx++]; if (string.Compare(field.Name, par.Name.ToLower(), StringComparison.OrdinalIgnoreCase) != 0) { throw new BTDBException($"Parameter and key mismatch in {methodName}, {field.Name}!={par.Name}."); } if (!field.Handler.IsCompatibleWith(par.ParameterType, FieldHandlerOptions.Orderable)) { throw new BTDBException($"Parameter type mismatch in {methodName} (expected '{field.Handler.HandledType().ToSimpleName()}' but '{par.ParameterType.ToSimpleName()}' found)."); } SaveKeyFieldFromArgument(ilGenerator, field, idx, writerLoc); } return((ushort)(idx + usedApartFieldsCount)); }
void CopyFromBuffer(IILGen ilGenerator, int bufferIdx, int skFieldIdx, ref BufferInfo bi, Dictionary <int, MemorizedPositionWithLength> outOfOrderPKParts, List <TableFieldInfo> pks, IList <FieldId> skFields, IILLocal positionLoc, IILLocal memoPositionLoc, Action <IILGen> pushWriter) { for (var idx = bi.ActualFieldIdx; idx < skFieldIdx; idx++) { var field = skFields[idx]; if (field.IsFromPrimaryKey) { outOfOrderPKParts[(int)field.Index] = SkipWithMemorizing(bufferIdx, ilGenerator, bi.PushReader, pks[(int)field.Index].Handler, positionLoc); } else { var f = ClientRelationVersionInfo.GetSecondaryKeyField((int)field.Index); f.Handler.Skip(ilGenerator, bi.PushReader); } } var skField = skFields[skFieldIdx]; GenerateCopyFieldFromByteBufferToWriterIl(ilGenerator, pks[(int)skField.Index].Handler, bi.PushReader, pushWriter, positionLoc, memoPositionLoc); bi.ActualFieldIdx = skFieldIdx + 1; }
void MemorizeCurrentPosition(IILGen ilGenerator, Action <IILGen> pushReader, IILLocal memoPositionLoc) { ilGenerator .Do(pushReader) .Call(() => default(ByteArrayReader).MemorizeCurrentPosition()) .Stloc(memoPositionLoc); }
void CreateMethodContains(IILGen ilGenerator, Type relationDBManipulatorType, ParameterInfo[] methodParameters, IDictionary <string, MethodInfo> apartFields, Action <IILGen> pushWriter, IILLocal writerLoc) { //ByteBufferWriter.WriteVUInt32(RelationInfo.Id); WriteIdIl(ilGenerator, pushWriter, (int)_relationInfo.Id); var primaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetPrimaryKeyFields(); var count = SaveMethodParameters(ilGenerator, "Contains", methodParameters, methodParameters.Length, apartFields, primaryKeyFields, writerLoc); if (count != primaryKeyFields.Count) { throw new BTDBException($"Number of parameters in Contains does not match primary key count {primaryKeyFields.Count}."); } //call manipulator.Contains ilGenerator .Ldarg(0); //manipulator //call byteBuffer.data var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("Contains")); }
internal void Prepare() { if (MainLocal != null) return; MainLocal = _context.IL.DeclareLocal(typeof(object[]), "instances"); _context.PushToILStack(Need.ContainerNeed); _context.IL .Castclass(typeof(ContainerImpl)) .Ldfld(() => default(ContainerImpl).Instances) .Stloc(MainLocal); }
void CreateSaverIl(IILGen ilGen, IEnumerable <TableFieldInfo> fields, Action <IILGen> pushInstance, Action <IILGen> pushRelationIface, Action <IILGen> pushWriter, Action <IILGen> pushTransaction) { var anyNeedsCtx = fields.Any(tfi => tfi.Handler.NeedsCtx()); IILLocal writerCtxLocal = null; if (anyNeedsCtx) { writerCtxLocal = ilGen.DeclareLocal(typeof(IWriterCtx)); ilGen .Do(pushTransaction) .Do(pushWriter) .Newobj(() => new DBWriterCtx(null, null)) .Stloc(writerCtxLocal); } var props = ClientType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var field in fields) { var getter = props.First(p => GetPersistentName(p) == field.Name).GetGetMethod(true); Action <IILGen> writerOrCtx; var handler = field.Handler.SpecializeSaveForType(getter.ReturnType); if (handler.NeedsCtx()) { writerOrCtx = il => il.Ldloc(writerCtxLocal); } else { writerOrCtx = pushWriter; } MethodInfo apartFieldGetter = null; if (pushRelationIface != null) { ApartFields.TryGetValue(field.Name, out apartFieldGetter); } handler.Save(ilGen, writerOrCtx, il => { if (apartFieldGetter != null) { il.Do(pushRelationIface); getter = apartFieldGetter; } else { il.Do(pushInstance); } il.Callvirt(getter); _relationInfoResolver.TypeConvertorGenerator.GenerateConversion(getter.ReturnType, handler.HandledType())(il); }); } }
void CreateMethodFindById(IILGen ilGenerator, Type relationDBManipulatorType, string methodName, ParameterInfo[] methodParameters, Type methodReturnType, IDictionary <string, MethodInfo> apartFields, Action <IILGen> pushWriter, IILLocal writerLoc) { var isPrefixBased = ReturnsEnumerableOfClientType(methodReturnType, _relationInfo.ClientType); if (isPrefixBased) { WriteShortPrefixIl(ilGenerator, pushWriter, _relationInfo.Prefix); } else { WriteShortPrefixIl(ilGenerator, pushWriter, ObjectDB.AllRelationsPKPrefix); //ByteBufferWriter.WriteVUInt32(RelationInfo.Id); WriteIdIl(ilGenerator, pushWriter, (int)_relationInfo.Id); } var primaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetPrimaryKeyFields(); var count = SaveMethodParameters(ilGenerator, methodName, methodParameters, methodParameters.Length, apartFields, primaryKeyFields, writerLoc); if (!isPrefixBased && count != primaryKeyFields.Count) { throw new BTDBException( $"Number of parameters in {methodName} does not match primary key count {primaryKeyFields.Count}."); } //call manipulator.FindBy_ ilGenerator .Ldarg(0); //manipulator //call byteBuffer.data var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Call(dataGetter); if (isPrefixBased) { ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("FindByPrimaryKeyPrefix")); } else { ilGenerator.LdcI4(ShouldThrowWhenKeyNotFound(methodName, methodReturnType) ? 1 : 0); ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("FindByIdOrDefault")); if (methodReturnType == typeof(void)) { ilGenerator.Pop(); } } }
void CopyFromMemorizedPosition(IILGen ilGenerator, Action <IILGen> pushReader, Action <IILGen> pushWriter, MemorizedPositionWithLength memo, IILLocal memoPositionLoc) { MemorizeCurrentPosition(ilGenerator, pushReader, memoPositionLoc); ilGenerator .Do(pushWriter) //[W] .Do(pushReader) //[W,VR] .Ldloc(memo.Length) //[W, VR, readLen] .Ldloc(memo.Pos) //[W, VR, readLen, Memorize] .Callvirt(() => default(IMemorizedPosition).Restore()) //[W, VR] .Call(() => default(ByteArrayReader).ReadByteArrayRaw(0)) //[W, byte[]] .Call(() => default(AbstractBufferedWriter).WriteByteArrayRaw(null)) //[] .Ldloc(memoPositionLoc) //[Memorize] .Callvirt(() => default(IMemorizedPosition).Restore()); //[] }
void WritePrimaryKeyPrefixFinishedByAdvancedEnumerator(MethodInfo method, ParameterInfo[] parameters, IILMethod reqMethod, int prefixParamCount, ushort advEnumParamOrder, Type advEnumParam, TableFieldInfo field, IILLocal emptyBufferLoc) { reqMethod.Generator.Ldarg(0); SavePKListPrefixBytes(reqMethod.Generator, method.Name, parameters, _relationInfo.ApartFields); reqMethod.Generator .LdcI4(prefixParamCount + _relationInfo.ApartFields.Count) .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("Order")) .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("StartProposition")); FillBufferWhenNotIgnoredKeyPropositionIl(advEnumParamOrder, field, emptyBufferLoc, advEnumParam.GetField("Start"), reqMethod.Generator); reqMethod.Generator .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("EndProposition")); FillBufferWhenNotIgnoredKeyPropositionIl(advEnumParamOrder, field, emptyBufferLoc, advEnumParam.GetField("End"), reqMethod.Generator); }
void CreateMethodFindBy(IILGen ilGenerator, Type relationDBManipulatorType, string methodName, ParameterInfo[] methodParameters, Type methodReturnType, IDictionary <string, MethodInfo> apartFields, Action <IILGen> pushWriter, IILLocal writerLoc) { bool allowDefault = false; var skName = methodName.Substring(6); if (skName.EndsWith("OrDefault")) { skName = skName.Substring(0, skName.Length - 9); allowDefault = true; } WriteShortPrefixIl(ilGenerator, pushWriter, ObjectDB.AllRelationsSKPrefix); var skIndex = _relationInfo.ClientRelationVersionInfo.GetSecondaryKeyIndex(skName); //ByteBuffered.WriteVUInt32(RelationInfo.Id); WriteIdIl(ilGenerator, pushWriter, (int)_relationInfo.Id); //ByteBuffered.WriteVUInt32(skIndex); WriteIdIl(ilGenerator, pushWriter, (int)skIndex); var secondaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetSecondaryKeyFields(skIndex); SaveMethodParameters(ilGenerator, methodName, methodParameters, methodParameters.Length, apartFields, secondaryKeyFields, writerLoc); //call public T FindBySecondaryKeyOrDefault(uint secondaryKeyIndex, uint prefixParametersCount, ByteBuffer secKeyBytes, bool throwWhenNotFound) ilGenerator.Ldarg(0); //manipulator ilGenerator.LdcI4((int)skIndex); ilGenerator.LdcI4(methodParameters.Length + apartFields.Count); //call byteBuffer.data var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); if (ReturnsEnumerableOfClientType(methodReturnType, _relationInfo.ClientType)) { ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("FindBySecondaryKey")); } else { ilGenerator.LdcI4(allowDefault ? 0 : 1); //? should throw ilGenerator.Callvirt(relationDBManipulatorType.GetMethod("FindBySecondaryKeyOrDefault")); } }
void GenerateCopyFieldFromByteBufferToWriterIl(IILGen ilGenerator, IFieldHandler handler, Action <IILGen> pushReader, Action <IILGen> pushWriter, IILLocal positionLoc, IILLocal memoPositionLoc) { MemorizeCurrentPosition(ilGenerator, pushReader, memoPositionLoc); StoreCurrentPosition(ilGenerator, pushReader, positionLoc); handler.Skip(ilGenerator, pushReader); ilGenerator .Do(pushWriter) //[W] .Do(pushReader) //[W,VR] .Dup() //[W, VR, VR] .Callvirt(() => default(ByteArrayReader).GetCurrentPosition()) //[W, VR, posNew]; .Ldloc(positionLoc) //[W, VR, posNew, posOld] .Sub() //[W, VR, readLen] .ConvI4() //[W, VR, readLen(i)] .Ldloc(memoPositionLoc) //[W, VR, readLen, Memorize] .Callvirt(() => default(IMemorizedPosition).Restore()) //[W, VR, readLen] .Call(() => default(ByteArrayReader).ReadByteArrayRaw(0)) //[W, byte[]] .Call(() => default(AbstractBufferedWriter).WriteByteArrayRaw(null)); //[] }
public void FreeTemps() { Local = null; }
internal static void FillBufferWhenNotIgnoredKeyPropositionIl(ushort advEnumParamOrder, TableFieldInfo field, IILLocal emptyBufferLoc, FieldInfo instField, IILGen ilGenerator) { //stack contains KeyProposition var ignoreLabel = ilGenerator.DefineLabel(instField + "_ignore"); var doneLabel = ilGenerator.DefineLabel(instField + "_done"); var writerLoc = ilGenerator.DeclareLocal(typeof(AbstractBufferedWriter)); ilGenerator .Dup() .LdcI4((int)KeyProposition.Ignored) .BeqS(ignoreLabel) .Newobj(() => new ByteBufferWriter()) .Stloc(writerLoc); field.Handler.Save(ilGenerator, il => il.Ldloc(writerLoc), il => il.Ldarg(advEnumParamOrder).Ldfld(instField)); var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); ilGenerator .Br(doneLabel) .Mark(ignoreLabel) .Ldloc(emptyBufferLoc) .Mark(doneLabel); }
public static IILGen Stloc(this IILGen il, IILLocal localBuilder) { il.Emit(OpCodes.Stloc, localBuilder); return(il); }
public static IILGen Ldloca(this IILGen il, IILLocal localBuilder) { il.Emit(OpCodes.Ldloca, localBuilder); return(il); }
public void Add(ICReg key, IILLocal local) { _map.Add(key, local); }
public void Emit(OpCode opCode, IILLocal ilLocal) { _sourceCodeWriter.MarkAndWriteLine(_ilGenerator, string.Format("{0} {1} {3} {2}", opCode, ilLocal.Index, ((ILLocalImpl)ilLocal).Name, ilLocal.LocalType.ToSimpleName())); _ilGenerator.Emit(opCode, ((ILLocalImpl)ilLocal).LocalBuilder); }
public EmitILLocal(OpCode opCode, IILLocal ilLocal) { _opCode = opCode; _ilLocal = ilLocal; }
public void Emit(OpCode opCode, IILLocal ilLocal) { _instructions.Add(new EmitILLocal(opCode, ilLocal)); }
public void Emit(OpCode opCode, IILLocal ilLocal) { _ilGenerator.Emit(opCode, ((ILLocalImpl)ilLocal).LocalBuilder); }
static void SaveKeyFieldFromArgument(IILGen ilGenerator, TableFieldInfo field, ushort parameterId, Type parameterType, IILLocal writerLoc) { field.Handler.SpecializeSaveForType(parameterType).Save(ilGenerator, il => il.Ldloc(writerLoc), il => il.Ldarg(parameterId)); }
MemorizedPositionWithLength SkipWithMemorizing(int activeBuffer, IILGen ilGenerator, Action <IILGen> pushReader, IFieldHandler handler, IILLocal tempPosition) { var memoPos = ilGenerator.DeclareLocal(typeof(IMemorizedPosition)); var memoLen = ilGenerator.DeclareLocal(typeof(int)); var position = new MemorizedPositionWithLength { BufferIndex = activeBuffer, Pos = memoPos, Length = memoLen }; MemorizeCurrentPosition(ilGenerator, pushReader, memoPos); StoreCurrentPosition(ilGenerator, pushReader, tempPosition); handler.Skip(ilGenerator, pushReader); ilGenerator .Do(pushReader) //[VR] .Callvirt(() => default(ByteArrayReader).GetCurrentPosition()) //[posNew]; .Ldloc(tempPosition) //[posNew, posOld] .Sub() //[readLen] .ConvI4() //[readLen(i)] .Stloc(memoLen); //[] return(position); }
static void SaveKeyFieldFromApartField(IILGen ilGenerator, TableFieldInfo field, MethodInfo fieldGetter, IILLocal writerLoc) { field.Handler.SpecializeSaveForType(fieldGetter.ReturnType).Save(ilGenerator, il => il.Ldloc(writerLoc), il => il.Ldarg(0).Callvirt(fieldGetter)); }
void CreateMethodListById(IILGen ilGenerator, Type relationDBManipulatorType, string methodName, ParameterInfo[] methodParameters, IDictionary <string, MethodInfo> apartFields, Action <IILGen> pushWriter, IILLocal writerLoc) { WriteShortPrefixIl(ilGenerator, pushWriter, _relationInfo.Prefix); var primaryKeyFields = _relationInfo.ClientRelationVersionInfo.GetPrimaryKeyFields(); var paramsCount = SaveMethodParameters(ilGenerator, methodName, methodParameters, methodParameters.Length, apartFields, primaryKeyFields, writerLoc); //call manipulator.GetEnumerator(tr, byteBuffer) ilGenerator .Ldarg(0); //manipulator //call byteBuffer.data var dataGetter = typeof(ByteBufferWriter).GetProperty("Data").GetGetMethod(true); ilGenerator.Ldloc(writerLoc).Callvirt(dataGetter); ilGenerator.LdcI4(paramsCount + apartFields.Count); ilGenerator.Callvirt(relationDBManipulatorType.GetMethod(methodName)); }
public void ReplayTo(IILGen target) { Local = target.DeclareLocal(_type, _name, _pinned); Debug.Assert(Local.Index == Index); }