| File: System\Linq\Expressions\Interpreter\NotEqualInstruction.cs | Web Access |
| Project: src\runtime\src\libraries\System.Linq.Expressions\src\System.Linq.Expressions.csproj (System.Linq.Expressions) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Dynamic.Utils; namespace System.Linq.Expressions.Interpreter { internal abstract class NotEqualInstruction : Instruction { // Perf: EqualityComparer<T> but is 3/2 to 2 times slower. private static Instruction? s_reference, s_Boolean, s_SByte, s_Int16, s_Char, s_Int32, s_Int64, s_Byte, s_UInt16, s_UInt32, s_UInt64, s_Single, s_Double; private static Instruction? s_SByteLiftedToNull, s_Int16LiftedToNull, s_CharLiftedToNull, s_Int32LiftedToNull, s_Int64LiftedToNull, s_ByteLiftedToNull, s_UInt16LiftedToNull, s_UInt32LiftedToNull, s_UInt64LiftedToNull, s_SingleLiftedToNull, s_DoubleLiftedToNull; public override int ConsumedStack => 2; public override int ProducedStack => 1; public override string InstructionName => "NotEqual"; private NotEqualInstruction() { } private sealed class NotEqualBoolean : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((bool)left != (bool)right); } return 1; } } private sealed class NotEqualSByte : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((sbyte)left != (sbyte)right); } return 1; } } private sealed class NotEqualInt16 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((short)left != (short)right); } return 1; } } private sealed class NotEqualChar : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((char)left != (char)right); } return 1; } } private sealed class NotEqualInt32 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((int)left != (int)right); } return 1; } } private sealed class NotEqualInt64 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((long)left != (long)right); } return 1; } } private sealed class NotEqualByte : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((byte)left != (byte)right); } return 1; } } private sealed class NotEqualUInt16 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((ushort)left != (ushort)right); } return 1; } } private sealed class NotEqualUInt32 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((uint)left != (uint)right); } return 1; } } private sealed class NotEqualUInt64 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((ulong)left != (ulong)right); } return 1; } } private sealed class NotEqualSingle : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((float)left != (float)right); } return 1; } } private sealed class NotEqualDouble : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null) { frame.Push(right != null); } else if (right == null) { frame.Push(true); } else { frame.Push((double)left != (double)right); } return 1; } } private sealed class NotEqualReference : NotEqualInstruction { public override int Run(InterpretedFrame frame) { frame.Push(frame.Pop() != frame.Pop()); return 1; } } private sealed class NotEqualSByteLiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((sbyte)left != (sbyte)right); } return 1; } } private sealed class NotEqualInt16LiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((short)left != (short)right); } return 1; } } private sealed class NotEqualCharLiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((char)left != (char)right); } return 1; } } private sealed class NotEqualInt32LiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((int)left != (int)right); } return 1; } } private sealed class NotEqualInt64LiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((long)left != (long)right); } return 1; } } private sealed class NotEqualByteLiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((byte)left != (byte)right); } return 1; } } private sealed class NotEqualUInt16LiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((ushort)left != (ushort)right); } return 1; } } private sealed class NotEqualUInt32LiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((uint)left != (uint)right); } return 1; } } private sealed class NotEqualUInt64LiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((ulong)left != (ulong)right); } return 1; } } private sealed class NotEqualSingleLiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((float)left != (float)right); } return 1; } } private sealed class NotEqualDoubleLiftedToNull : NotEqualInstruction { public override int Run(InterpretedFrame frame) { object? right = frame.Pop(); object? left = frame.Pop(); if (left == null || right == null) { frame.Push(null); } else { frame.Push((double)left != (double)right); } return 1; } } public static Instruction Create(Type type, bool liftedToNull) { if (liftedToNull) { switch (type.GetNonNullableType().GetTypeCode()) { case TypeCode.Boolean: return ExclusiveOrInstruction.Create(type); case TypeCode.SByte: return s_SByteLiftedToNull ??= new NotEqualSByteLiftedToNull(); case TypeCode.Int16: return s_Int16LiftedToNull ??= new NotEqualInt16LiftedToNull(); case TypeCode.Char: return s_CharLiftedToNull ??= new NotEqualCharLiftedToNull(); case TypeCode.Int32: return s_Int32LiftedToNull ??= new NotEqualInt32LiftedToNull(); case TypeCode.Int64: return s_Int64LiftedToNull ??= new NotEqualInt64LiftedToNull(); case TypeCode.Byte: return s_ByteLiftedToNull ??= new NotEqualByteLiftedToNull(); case TypeCode.UInt16: return s_UInt16LiftedToNull ??= new NotEqualUInt16LiftedToNull(); case TypeCode.UInt32: return s_UInt32LiftedToNull ??= new NotEqualUInt32LiftedToNull(); case TypeCode.UInt64: return s_UInt64LiftedToNull ??= new NotEqualUInt64LiftedToNull(); case TypeCode.Single: return s_SingleLiftedToNull ??= new NotEqualSingleLiftedToNull(); default: Debug.Assert(type.GetNonNullableType().GetTypeCode() == TypeCode.Double); return s_DoubleLiftedToNull ??= new NotEqualDoubleLiftedToNull(); } } else { switch (type.GetNonNullableType().GetTypeCode()) { case TypeCode.Boolean: return s_Boolean ??= new NotEqualBoolean(); case TypeCode.SByte: return s_SByte ??= new NotEqualSByte(); case TypeCode.Int16: return s_Int16 ??= new NotEqualInt16(); case TypeCode.Char: return s_Char ??= new NotEqualChar(); case TypeCode.Int32: return s_Int32 ??= new NotEqualInt32(); case TypeCode.Int64: return s_Int64 ??= new NotEqualInt64(); case TypeCode.Byte: return s_Byte ??= new NotEqualByte(); case TypeCode.UInt16: return s_UInt16 ??= new NotEqualUInt16(); case TypeCode.UInt32: return s_UInt32 ??= new NotEqualUInt32(); case TypeCode.UInt64: return s_UInt64 ??= new NotEqualUInt64(); case TypeCode.Single: return s_Single ??= new NotEqualSingle(); case TypeCode.Double: return s_Double ??= new NotEqualDouble(); default: // Nullable only valid if one operand is constant null, so this assert is slightly too broad. Debug.Assert(type.IsNullableOrReferenceType()); return s_reference ??= new NotEqualReference(); } } } } }