1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Collections.Generic;
18 using System.Diagnostics;
19 using System.Reflection;
20 using System.Runtime.CompilerServices;
21 using Microsoft.Scripting.Runtime;
22 using Microsoft.Scripting.Utils;
24 namespace Microsoft.Scripting.Interpreter {
25 internal abstract class NotEqualInstruction : Instruction {
26 // Perf: EqualityComparer<T> but is 3/2 to 2 times slower.
27 private static Instruction _Reference, _Boolean, _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double;
28 private static Instruction _BooleanLifted, _SByteLifted, _Int16Lifted, _CharLifted, _Int32Lifted, _Int64Lifted,
29 _ByteLifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _SingleLifted, _DoubleLifted;
31 public override int ConsumedStack { get { return 2; } }
32 public override int ProducedStack { get { return 1; } }
34 private NotEqualInstruction() {
37 public bool LiftedToNull { get; set; }
39 internal sealed class NotEqualBoolean : NotEqualInstruction {
40 public override int Run(InterpretedFrame frame) {
41 object l = frame.Data[frame.StackIndex - 2];
42 object r = frame.Data[frame.StackIndex - 1];
43 if (l == null || r == null)
44 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
46 frame.Data[frame.StackIndex - 2] = (Boolean)l != (Boolean)r;
53 internal sealed class NotEqualSByte : NotEqualInstruction {
54 public override int Run(InterpretedFrame frame) {
55 object l = frame.Data[frame.StackIndex - 2];
56 object r = frame.Data[frame.StackIndex - 1];
57 if (l == null || r == null)
58 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
60 frame.Data[frame.StackIndex - 2] = (SByte)l != (SByte)r;
67 internal sealed class NotEqualInt16 : NotEqualInstruction {
68 public override int Run(InterpretedFrame frame) {
69 object l = frame.Data[frame.StackIndex - 2];
70 object r = frame.Data[frame.StackIndex - 1];
71 if (l == null || r == null)
72 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
74 frame.Data[frame.StackIndex - 2] = (Int16)l != (Int16)r;
81 internal sealed class NotEqualChar : NotEqualInstruction {
82 public override int Run(InterpretedFrame frame) {
83 object l = frame.Data[frame.StackIndex - 2];
84 object r = frame.Data[frame.StackIndex - 1];
85 if (l == null || r == null)
86 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
88 frame.Data[frame.StackIndex - 2] = (Char)l != (Char)r;
95 internal sealed class NotEqualInt32 : NotEqualInstruction {
96 public override int Run(InterpretedFrame frame) {
97 object l = frame.Data[frame.StackIndex - 2];
98 object r = frame.Data[frame.StackIndex - 1];
99 if (l == null || r == null)
100 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
102 frame.Data[frame.StackIndex - 2] = (Int32)l != (Int32)r;
108 internal sealed class NotEqualInt64 : NotEqualInstruction {
109 public override int Run(InterpretedFrame frame) {
110 object l = frame.Data[frame.StackIndex - 2];
111 object r = frame.Data[frame.StackIndex - 1];
112 if (l == null || r == null)
113 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
115 frame.Data[frame.StackIndex - 2] = (Int64)l != (Int64)r;
122 internal sealed class NotEqualByte : NotEqualInstruction {
123 public override int Run(InterpretedFrame frame) {
124 object l = frame.Data[frame.StackIndex - 2];
125 object r = frame.Data[frame.StackIndex - 1];
126 if (l == null || r == null)
127 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
129 frame.Data[frame.StackIndex - 2] = (Byte)l != (Byte)r;
136 internal sealed class NotEqualUInt16 : NotEqualInstruction {
137 public override int Run(InterpretedFrame frame) {
138 object l = frame.Data[frame.StackIndex - 2];
139 object r = frame.Data[frame.StackIndex - 1];
140 if (l == null || r == null)
141 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
143 frame.Data[frame.StackIndex - 2] = (UInt16)l != (UInt16)r;
150 internal sealed class NotEqualUInt32 : NotEqualInstruction {
151 public override int Run(InterpretedFrame frame) {
152 object l = frame.Data[frame.StackIndex - 2];
153 object r = frame.Data[frame.StackIndex - 1];
154 if (l == null || r == null)
155 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
157 frame.Data[frame.StackIndex - 2] = (UInt32)l != (UInt32)r;
164 internal sealed class NotEqualUInt64 : NotEqualInstruction {
165 public override int Run(InterpretedFrame frame) {
166 object l = frame.Data[frame.StackIndex - 2];
167 object r = frame.Data[frame.StackIndex - 1];
168 if (l == null || r == null)
169 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
171 frame.Data[frame.StackIndex - 2] = (UInt64)l != (UInt64)r;
178 internal sealed class NotEqualSingle : NotEqualInstruction {
179 public override int Run(InterpretedFrame frame) {
180 object l = frame.Data[frame.StackIndex - 2];
181 object r = frame.Data[frame.StackIndex - 1];
182 if (l == null || r == null)
183 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
185 frame.Data[frame.StackIndex - 2] = (Single)l != (Single)r;
192 internal sealed class NotEqualDouble : NotEqualInstruction {
193 public override int Run(InterpretedFrame frame) {
194 object l = frame.Data[frame.StackIndex - 2];
195 object r = frame.Data[frame.StackIndex - 1];
196 if (l == null || r == null)
197 frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r;
199 frame.Data[frame.StackIndex - 2] = (Double)l != (Double)r;
206 internal sealed class NotEqualReference : NotEqualInstruction {
207 public override int Run(InterpretedFrame frame) {
208 frame.Push(frame.Pop() != frame.Pop());
213 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
214 public static Instruction Create(Type type) {
215 // Boxed enums can be unboxed as their underlying types:
216 switch ((type.IsEnum() ? Enum.GetUnderlyingType(type) : type).GetTypeCode()) {
217 case TypeCode.Boolean: return _Boolean ?? (_Boolean = new NotEqualBoolean());
218 case TypeCode.SByte: return _SByte ?? (_SByte = new NotEqualSByte());
219 case TypeCode.Byte: return _Byte ?? (_Byte = new NotEqualByte());
220 case TypeCode.Char: return _Char ?? (_Char = new NotEqualChar());
221 case TypeCode.Int16: return _Int16 ?? (_Int16 = new NotEqualInt16());
222 case TypeCode.Int32: return _Int32 ?? (_Int32 = new NotEqualInt32());
223 case TypeCode.Int64: return _Int64 ?? (_Int64 = new NotEqualInt64());
225 case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new NotEqualInt16());
226 case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new NotEqualInt32());
227 case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new NotEqualInt64());
229 case TypeCode.Single: return _Single ?? (_Single = new NotEqualSingle());
230 case TypeCode.Double: return _Double ?? (_Double = new NotEqualDouble());
232 case TypeCode.Object:
233 if (!type.IsValueType()) {
234 return _Reference ?? (_Reference = new NotEqualReference());
237 throw new NotImplementedException();
240 throw new NotImplementedException();
244 public static Instruction CreateLifted(Type type) {
245 // Boxed enums can be unboxed as their underlying types:
246 switch ((type.IsEnum() ? Enum.GetUnderlyingType(type) : type).GetTypeCode()) {
247 case TypeCode.Boolean: return _BooleanLifted ?? (_BooleanLifted = new NotEqualBoolean() { LiftedToNull = true });
248 case TypeCode.SByte: return _SByteLifted ?? (_SByteLifted = new NotEqualSByte() { LiftedToNull = true });
249 case TypeCode.Byte: return _ByteLifted ?? (_ByteLifted = new NotEqualByte() { LiftedToNull = true });
250 case TypeCode.Char: return _CharLifted ?? (_CharLifted = new NotEqualChar() { LiftedToNull = true });
251 case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new NotEqualInt16() { LiftedToNull = true });
252 case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new NotEqualInt32() { LiftedToNull = true });
253 case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new NotEqualInt64() { LiftedToNull = true });
255 case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new NotEqualInt16() { LiftedToNull = true });
256 case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new NotEqualInt32() { LiftedToNull = true });
257 case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new NotEqualInt64() { LiftedToNull = true });
259 case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new NotEqualSingle() { LiftedToNull = true });
260 case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new NotEqualDouble() { LiftedToNull = true });
263 throw Assert.Unreachable;
267 public override string ToString() {