예제 #1
0
        public void Build(Type objectType, bool detectCycles, MethodBuilder staticMethodBuilder)
        {
            using var il = staticMethodBuilder.CreateILEmitter();

            il.DefineLabel(out var exit);

            var needReferenceComparison = !objectType.ImplementsGenericInterface(typeof(IEnumerable<>)); // collections do reference comparisons anyway

            if (needReferenceComparison) {
                if (!objectType.IsValueType) {
                    il.EmitReferenceComparison(LoadArgument(Arg.X), LoadArgument(Arg.Y), Ret(1));
                } else if (objectType.IsNullable()) {
                    il.EmitCheckNullablesForValue(LoadArgumentAddress(Arg.X), LoadArgumentAddress(Arg.Y), objectType, exit);
                }
            }

            if (detectCycles) {
                EmitCycleDetection(il, objectType);
            }

            var emitter = _resolver.GetComparisonEmitter(new ArgumentVariable(objectType));

            emitter.Emit(il, exit);

            if (detectCycles) {
                il.Emit(Remove(Arg.SetX, Arg.X, objectType))
                  .Emit(Remove(Arg.SetY, Arg.Y, objectType));
            }

            il.Emit(emitter.EmitCheckForResult(exit))
              .MarkLabel(exit)
              .Ret(1);
        }
        public void Build(Type objectType, bool detectCycles, MethodBuilder staticMethodBuilder)
        {
            using var il = staticMethodBuilder.CreateILEmitter();

            var isCollection  = objectType.ImplementsGenericInterface(typeof(IEnumerable <>));
            var needNullCheck = !objectType.IsValueType && !isCollection; // collections do null check anyway

            if (needNullCheck)
            {
                il.LoadArgument(Arg.Input)
                .Brtrue_S(out var next)
                .Ret(0)
                .MarkLabel(next);
            }

            if (detectCycles)
            {
                EmitCycleDetection(il, objectType);
            }

            _resolver.GetHasherEmitter(new ArgumentVariable(objectType)).Emit(il);

            if (detectCycles)
            {
                il.Emit(Remove(Arg.CycleSet, Arg.Input, objectType));
            }

            il.Ret();
        }