예제 #1
0
 void StoreCurrentPosition(IILGen ilGenerator, Action <IILGen> pushReader, IILLocal positionLoc)
 {
     ilGenerator
     .Do(pushReader)
     .Callvirt(() => default(ByteArrayReader).GetCurrentPosition())
     .Stloc(positionLoc);
 }
예제 #2
0
        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));
        }
예제 #3
0
        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;
        }
예제 #4
0
 void MemorizeCurrentPosition(IILGen ilGenerator, Action <IILGen> pushReader, IILLocal memoPositionLoc)
 {
     ilGenerator
     .Do(pushReader)
     .Call(() => default(ByteArrayReader).MemorizeCurrentPosition())
     .Stloc(memoPositionLoc);
 }
예제 #5
0
        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"));
        }
예제 #6
0
 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);
 }
예제 #7
0
        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);
                });
            }
        }
예제 #8
0
        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();
                }
            }
        }
예제 #9
0
 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());              //[]
 }
예제 #10
0
 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);
 }
예제 #11
0
        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"));
            }
        }
예제 #12
0
        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)); //[]
        }
예제 #13
0
 public void FreeTemps()
 {
     Local = null;
 }
예제 #14
0
        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);
        }
예제 #15
0
 public static IILGen Stloc(this IILGen il, IILLocal localBuilder)
 {
     il.Emit(OpCodes.Stloc, localBuilder);
     return(il);
 }
예제 #16
0
 public static IILGen Ldloca(this IILGen il, IILLocal localBuilder)
 {
     il.Emit(OpCodes.Ldloca, localBuilder);
     return(il);
 }
예제 #17
0
 public void Add(ICReg key, IILLocal local)
 {
     _map.Add(key, local);
 }
예제 #18
0
 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);
 }
예제 #19
0
 public EmitILLocal(OpCode opCode, IILLocal ilLocal)
 {
     _opCode  = opCode;
     _ilLocal = ilLocal;
 }
예제 #20
0
 public void Add(ICReg key, IILLocal local)
 {
     _map.Add(key, local);
 }
예제 #21
0
 public void FreeTemps()
 {
     Local = null;
 }
예제 #22
0
 public void Emit(OpCode opCode, IILLocal ilLocal)
 {
     _instructions.Add(new EmitILLocal(opCode, ilLocal));
 }
예제 #23
0
파일: ILGenImpl.cs 프로젝트: mano-cz/BTDB
 public void Emit(OpCode opCode, IILLocal ilLocal)
 {
     _ilGenerator.Emit(opCode, ((ILLocalImpl)ilLocal).LocalBuilder);
 }
예제 #24
0
 public EmitILLocal(OpCode opCode, IILLocal ilLocal)
 {
     _opCode = opCode;
     _ilLocal = ilLocal;
 }
예제 #25
0
파일: ILGenImpl.cs 프로젝트: yardee/BTDB
 public void Emit(OpCode opCode, IILLocal ilLocal)
 {
     _ilGenerator.Emit(opCode, ((ILLocalImpl)ilLocal).LocalBuilder);
 }
예제 #26
0
 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));
 }
예제 #27
0
        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);
        }
예제 #28
0
 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));
 }
예제 #29
0
        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));
        }
예제 #30
0
 public void Emit(OpCode opCode, IILLocal ilLocal)
 {
     _instructions.Add(new EmitILLocal(opCode, ilLocal));
 }
예제 #31
0
 public void ReplayTo(IILGen target)
 {
     Local = target.DeclareLocal(_type, _name, _pinned);
     Debug.Assert(Local.Index == Index);
 }
예제 #32
0
 public void ReplayTo(IILGen target)
 {
     Local = target.DeclareLocal(_type, _name, _pinned);
     Debug.Assert(Local.Index == Index);
 }
예제 #33
0
 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);
 }