diff options
author | Marek Safar <marek.safar@gmail.com> | 2014-01-26 14:34:00 +0400 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2014-01-26 14:35:09 +0400 |
commit | f2eab9919dd6ab4548675197e4a7eaffd9816a6a (patch) | |
tree | d5318770896b3c3847405e1c395c2d9dea6b12aa /mcs/class/dlr | |
parent | 280f85db70b76e0f80605c9574a3bb3e17101a99 (diff) |
[dlr] Handle more expressions in interpreter
Diffstat (limited to 'mcs/class/dlr')
22 files changed, 1952 insertions, 275 deletions
diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AddInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AddInstruction.cs index 1f1775c180f..3846e4d215f 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AddInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AddInstruction.cs @@ -153,7 +153,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int16)checked((Int16)l + (Int16)r); + frame.Data[frame.StackIndex - 2] = checked((Int16)((Int16)l + (Int16)r)); frame.StackIndex--; return +1; } @@ -163,7 +163,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int64)checked((Int64)l + (Int64)r); + frame.Data[frame.StackIndex - 2] = checked((Int64)((Int64)l + (Int64)r)); frame.StackIndex--; return +1; } @@ -173,7 +173,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt16)checked((UInt16)l + (UInt16)r); + frame.Data[frame.StackIndex - 2] = checked((UInt16)((UInt16)l + (UInt16)r)); frame.StackIndex--; return +1; } @@ -183,7 +183,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt32)checked((UInt32)l + (UInt32)r); + frame.Data[frame.StackIndex - 2] = checked((UInt32)((UInt32)l + (UInt32)r)); frame.StackIndex--; return +1; } @@ -193,7 +193,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt64)checked((UInt64)l + (UInt64)r); + frame.Data[frame.StackIndex - 2] = checked((UInt64)((UInt64)l + (UInt64)r)); frame.StackIndex--; return +1; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AndInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AndInstruction.cs index 09ec87df22a..2b423f581f0 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AndInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/AndInstruction.cs @@ -34,6 +34,7 @@ using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { internal abstract class AndInstruction : Instruction { private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64, _Boolean; + private static Instruction _Int16Lifted, _Int32Lifted, _Int64Lifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _BooleanLifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -43,9 +44,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class AndInt32 : AndInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject((Int32)l & (Int32)r); + var l = (Int32)frame.Data[frame.StackIndex - 2]; + var r = (Int32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(l & r); frame.StackIndex--; return 1; } @@ -53,9 +54,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class AndInt16 : AndInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int16)((Int16)l & (Int16)r); + var l = (Int16)frame.Data[frame.StackIndex - 2]; + var r = (Int16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int16)(l & r); frame.StackIndex--; return 1; } @@ -63,9 +64,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class AndInt64 : AndInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int64)((Int64)l & (Int64)r); + var l = (Int64)frame.Data[frame.StackIndex - 2]; + var r = (Int64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int64)(l & r); frame.StackIndex--; return 1; } @@ -73,9 +74,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class AndUInt16 : AndInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt16)((UInt16)l & (UInt16)r); + var l = (UInt16)frame.Data[frame.StackIndex - 2]; + var r = (UInt16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt16)(l & r); frame.StackIndex--; return 1; } @@ -83,9 +84,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class AndUInt32 : AndInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt32)((UInt32)l & (UInt32)r); + var l = (UInt32)frame.Data[frame.StackIndex - 2]; + var r = (UInt32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt32)(l & r); frame.StackIndex--; return 1; } @@ -93,9 +94,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class AndUInt64 : AndInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt64)((UInt64)l & (UInt64)r); + var l = (UInt64)frame.Data[frame.StackIndex - 2]; + var r = (UInt64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt64)(l & r); frame.StackIndex--; return 1; } @@ -103,9 +104,79 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class AndBoolean : AndInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Boolean)((Boolean)l & (Boolean)r); + var l = (Boolean)frame.Data[frame.StackIndex - 2]; + var r = (Boolean)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Boolean)(l & r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class AndInt32Lifted : AndInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int32?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32?)(l & r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class AndInt16Lifted : AndInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int16?)frame.Data[frame.StackIndex - 2]; + var r = (Int16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int16?)(l & r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class AndInt64Lifted : AndInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int64?)frame.Data[frame.StackIndex - 2]; + var r = (Int64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int64?)(l & r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class AndUInt16Lifted : AndInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt16?)frame.Data[frame.StackIndex - 2]; + var r = (UInt16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt16?)(l & r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class AndUInt32Lifted : AndInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt32?)frame.Data[frame.StackIndex - 2]; + var r = (UInt32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt32?)(l & r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class AndUInt64Lifted : AndInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt64?)frame.Data[frame.StackIndex - 2]; + var r = (UInt64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt64?)(l & r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class AndBooleanLifted : AndInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Boolean?)frame.Data[frame.StackIndex - 2]; + var r = (Boolean?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Boolean?)(l & r); frame.StackIndex--; return 1; } @@ -127,6 +198,22 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new AndInt16Lifted()); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new AndInt32Lifted()); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new AndInt64Lifted()); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new AndUInt16Lifted()); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new AndUInt32Lifted()); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new AndUInt64Lifted()); + case TypeCode.Boolean: return _BooleanLifted ?? (_BooleanLifted = new AndBooleanLifted()); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "And()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ControlFlowInstructions.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ControlFlowInstructions.cs index 376488e08f9..b7549ee4b77 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ControlFlowInstructions.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ControlFlowInstructions.cs @@ -119,6 +119,34 @@ namespace Microsoft.Scripting.Interpreter { } } + internal sealed class BranchNullInstruction : OffsetInstruction { + private static Instruction[] _cache; + + public override Instruction[] Cache { + get { + if (_cache == null) { + _cache = new Instruction[CacheSize]; + } + return _cache; + } + } + + internal BranchNullInstruction() { + } + + public override int ConsumedStack { get { return 1; } } + + public override int Run(InterpretedFrame frame) { + Debug.Assert(_offset != Unknown); + + if (frame.Pop() == null) { + return _offset; + } + + return +1; + } + } + internal sealed class CoalescingBranchInstruction : OffsetInstruction { private static Instruction[] _cache; diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs index e4edde9bab2..38e904d3eae 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/EqualInstruction.cs @@ -25,6 +25,8 @@ namespace Microsoft.Scripting.Interpreter { internal abstract class EqualInstruction : Instruction { // Perf: EqualityComparer<T> but is 3/2 to 2 times slower. private static Instruction _Reference, _Boolean, _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double; + private static Instruction _BooleanLifted, _SByteLifted, _Int16Lifted, _CharLifted, _Int32Lifted, _Int64Lifted, + _ByteLifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _SingleLifted, _DoubleLifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -32,86 +34,171 @@ namespace Microsoft.Scripting.Interpreter { private EqualInstruction() { } + public bool LiftedToNull { get; set; } + internal sealed class EqualBoolean : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Boolean)frame.Pop()) == ((Boolean)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (Boolean)l == (Boolean)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualSByte : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((SByte)frame.Pop()) == ((SByte)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (SByte)l == (SByte)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualInt16 : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Int16)frame.Pop()) == ((Int16)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (Int16)l == (Int16)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualChar : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Char)frame.Pop()) == ((Char)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (Char)l == (Char)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualInt32 : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Int32)frame.Pop()) == ((Int32)frame.Pop())); - return +1; - } + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (Int32)l == (Int32)r; + + frame.StackIndex--; + return +1; } } internal sealed class EqualInt64 : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Int64)frame.Pop()) == ((Int64)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (Int64)l == (Int64)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualByte : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Byte)frame.Pop()) == ((Byte)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (Byte)l == (Byte)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualUInt16 : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((UInt16)frame.Pop()) == ((UInt16)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (UInt16)l == (UInt16)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualUInt32 : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((UInt32)frame.Pop()) == ((UInt32)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (UInt32)l == (UInt32)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualUInt64 : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((UInt64)frame.Pop()) == ((UInt64)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (UInt64)l == (UInt64)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualSingle : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Single)frame.Pop()) == ((Single)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (Single)l == (Single)r; + + frame.StackIndex--; return +1; } } internal sealed class EqualDouble : EqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Double)frame.Pop()) == ((Double)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l == r; + else + frame.Data[frame.StackIndex - 2] = (Double)l == (Double)r; + + frame.StackIndex--; return +1; } } @@ -154,6 +241,29 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + // Boxed enums can be unboxed as their underlying types: + switch ((type.IsEnum() ? Enum.GetUnderlyingType(type) : type).GetTypeCode()) { + case TypeCode.Boolean: return _BooleanLifted ?? (_BooleanLifted = new EqualBoolean() { LiftedToNull = true }); + case TypeCode.SByte: return _SByteLifted ?? (_SByteLifted = new EqualSByte() { LiftedToNull = true }); + case TypeCode.Byte: return _ByteLifted ?? (_ByteLifted = new EqualByte() { LiftedToNull = true }); + case TypeCode.Char: return _CharLifted ?? (_CharLifted = new EqualChar() { LiftedToNull = true }); + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new EqualInt16() { LiftedToNull = true }); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new EqualInt32() { LiftedToNull = true }); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new EqualInt64() { LiftedToNull = true }); + + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new EqualInt16() { LiftedToNull = true }); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new EqualInt32() { LiftedToNull = true }); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new EqualInt64() { LiftedToNull = true }); + + case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new EqualSingle() { LiftedToNull = true }); + case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new EqualDouble() { LiftedToNull = true }); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "Equal()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanInstruction.cs index a35f16b0e34..8849613fd51 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanInstruction.cs @@ -1,17 +1,30 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ +// +// GreaterThanInstruction.cs: +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Copyright 2014 Xamarin Inc +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// using System; using System.Collections.Generic; @@ -22,8 +35,9 @@ using Microsoft.Scripting.Runtime; using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { - internal abstract class GreaterThanInstruction : Instruction { + public abstract class GreaterThanInstruction : Instruction { private static Instruction _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double; + private static Instruction _SByteLifted, _Int16Lifted, _CharLifted, _Int32Lifted, _Int64Lifted, _ByteLifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _SingleLifted, _DoubleLifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -31,90 +45,158 @@ namespace Microsoft.Scripting.Interpreter { private GreaterThanInstruction() { } + public bool LiftedToNull { get; set; } + internal sealed class GreaterThanSByte : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - SByte right = (SByte)frame.Pop(); - frame.Push(((SByte)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (SByte)l > (SByte)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanInt16 : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - Int16 right = (Int16)frame.Pop(); - frame.Push(((Int16)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int16)l > (Int16)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanChar : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - Char right = (Char)frame.Pop(); - frame.Push(((Char)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Char)l > (Char)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanInt32 : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - Int32 right = (Int32)frame.Pop(); - frame.Push(((Int32)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int32)l > (Int32)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanInt64 : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - Int64 right = (Int64)frame.Pop(); - frame.Push(((Int64)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int64)l > (Int64)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanByte : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - Byte right = (Byte)frame.Pop(); - frame.Push(((Byte)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Byte)l > (Byte)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanUInt16 : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - UInt16 right = (UInt16)frame.Pop(); - frame.Push(((UInt16)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt16)l > (UInt16)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanUInt32 : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - UInt32 right = (UInt32)frame.Pop(); - frame.Push(((UInt32)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt32)l > (UInt32)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanUInt64 : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - UInt64 right = (UInt64)frame.Pop(); - frame.Push(((UInt64)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt64)l > (UInt64)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanSingle : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - Single right = (Single)frame.Pop(); - frame.Push(((Single)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Single)l > (Single)r; + + frame.StackIndex--; return +1; } } internal sealed class GreaterThanDouble : GreaterThanInstruction { public override int Run(InterpretedFrame frame) { - Double right = (Double)frame.Pop(); - frame.Push(((Double)frame.Pop()) > right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Double)l > (Double)r; + + frame.StackIndex--; return +1; } } @@ -139,6 +221,26 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.SByte: return _SByteLifted ?? (_SByteLifted = new GreaterThanSByte() { LiftedToNull = true }); + case TypeCode.Byte: return _ByteLifted ?? (_ByteLifted = new GreaterThanByte() { LiftedToNull = true }); + case TypeCode.Char: return _CharLifted ?? (_CharLifted = new GreaterThanChar() { LiftedToNull = true }); + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new GreaterThanInt16() { LiftedToNull = true }); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new GreaterThanInt32() { LiftedToNull = true }); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new GreaterThanInt64() { LiftedToNull = true }); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new GreaterThanUInt16() { LiftedToNull = true }); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new GreaterThanUInt32() { LiftedToNull = true }); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new GreaterThanUInt64() { LiftedToNull = true }); + case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new GreaterThanSingle() { LiftedToNull = true }); + case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new GreaterThanDouble() { LiftedToNull = true }); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "GreaterThan()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanOrEqualInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanOrEqualInstruction.cs new file mode 100644 index 00000000000..de2da8fd965 --- /dev/null +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/GreaterThanOrEqualInstruction.cs @@ -0,0 +1,248 @@ +// +// GreaterThanOrEqualInstruction.cs: +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Copyright 2014 Xamarin Inc +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.Scripting.Runtime; +using Microsoft.Scripting.Utils; + +namespace Microsoft.Scripting.Interpreter { + public abstract class GreaterThanOrEqualInstruction : Instruction { + private static Instruction _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double; + private static Instruction _SByteLifted, _Int16Lifted, _CharLifted, _Int32Lifted, _Int64Lifted, _ByteLifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _SingleLifted, _DoubleLifted; + + public override int ConsumedStack { get { return 2; } } + public override int ProducedStack { get { return 1; } } + + private GreaterThanOrEqualInstruction() { + } + + public bool LiftedToNull { get; set; } + + internal sealed class GreaterThanOrEqualSByte : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (SByte)l >= (SByte)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualInt16 : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int16)l >= (Int16)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualChar : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Char)l >= (Char)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualInt32 : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int32)l >= (Int32)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualInt64 : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int64)l >= (Int64)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualByte : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Byte)l >= (Byte)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualUInt16 : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt16)l >= (UInt16)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualUInt32 : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt32)l >= (UInt32)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualUInt64 : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt64)l >= (UInt64)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualSingle : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Single)l >= (Single)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class GreaterThanOrEqualDouble : GreaterThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Double)l >= (Double)r; + + frame.StackIndex--; + return +1; + } + } + + public static Instruction Create(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.SByte: return _SByte ?? (_SByte = new GreaterThanOrEqualSByte()); + case TypeCode.Byte: return _Byte ?? (_Byte = new GreaterThanOrEqualByte()); + case TypeCode.Char: return _Char ?? (_Char = new GreaterThanOrEqualChar()); + case TypeCode.Int16: return _Int16 ?? (_Int16 = new GreaterThanOrEqualInt16()); + case TypeCode.Int32: return _Int32 ?? (_Int32 = new GreaterThanOrEqualInt32()); + case TypeCode.Int64: return _Int64 ?? (_Int64 = new GreaterThanOrEqualInt64()); + case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new GreaterThanOrEqualUInt16()); + case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new GreaterThanOrEqualUInt32()); + case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new GreaterThanOrEqualUInt64()); + case TypeCode.Single: return _Single ?? (_Single = new GreaterThanOrEqualSingle()); + case TypeCode.Double: return _Double ?? (_Double = new GreaterThanOrEqualDouble()); + + default: + throw Assert.Unreachable; + } + } + + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.SByte: return _SByteLifted ?? (_SByteLifted = new GreaterThanOrEqualSByte() { LiftedToNull = true }); + case TypeCode.Byte: return _ByteLifted ?? (_ByteLifted = new GreaterThanOrEqualByte() { LiftedToNull = true }); + case TypeCode.Char: return _CharLifted ?? (_CharLifted = new GreaterThanOrEqualChar() { LiftedToNull = true }); + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new GreaterThanOrEqualInt16() { LiftedToNull = true }); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new GreaterThanOrEqualInt32() { LiftedToNull = true }); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new GreaterThanOrEqualInt64() { LiftedToNull = true }); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new GreaterThanOrEqualUInt16() { LiftedToNull = true }); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new GreaterThanOrEqualUInt32() { LiftedToNull = true }); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new GreaterThanOrEqualUInt64() { LiftedToNull = true }); + case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new GreaterThanOrEqualSingle() { LiftedToNull = true }); + case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new GreaterThanOrEqualDouble() { LiftedToNull = true }); + + default: + throw Assert.Unreachable; + } + } + + public override string ToString() { + return "GreaterThanOrEqual()"; + } + } +} diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionFactory.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionFactory.cs index ca0be0924d3..5f916ce64b6 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionFactory.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionFactory.cs @@ -69,6 +69,7 @@ namespace Microsoft.Scripting.Interpreter { internal protected abstract Instruction DefaultValue(); internal protected abstract Instruction NewArray(); internal protected abstract Instruction NewArrayInit(int elementCount); + internal protected abstract Instruction WrapToNullable(Type elementType); } public sealed class InstructionFactory<T> : InstructionFactory { @@ -81,6 +82,7 @@ namespace Microsoft.Scripting.Interpreter { private Instruction _defaultValue; private Instruction _newArray; private Instruction _typeAs; + private Instruction _nullableWrap; private InstructionFactory() { } @@ -111,5 +113,9 @@ namespace Microsoft.Scripting.Interpreter { internal protected override Instruction NewArrayInit(int elementCount) { return new NewArrayInitInstruction<T>(elementCount); } + + internal protected override Instruction WrapToNullable(Type elementType) { + return _nullableWrap ?? (_nullableWrap = new WrapToNullableInstruction<T>(elementType)); + } } } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionList.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionList.cs index 3fa74e9b967..28746e65c6b 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionList.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/InstructionList.cs @@ -664,52 +664,62 @@ namespace Microsoft.Scripting.Interpreter { #endregion - public void EmitShl(Type type) { - Emit(ShlInstruction.Create(type)); + public void EmitShl(Type type, bool lifted) { + Emit(lifted ? ShlInstruction.CreateLifted(type) : ShlInstruction.Create(type)); } - public void EmitShr(Type type) { - Emit(ShrInstruction.Create(type)); + public void EmitShr(Type type, bool lifted) { + Emit(lifted ? ShrInstruction.CreateLifted(type) : ShrInstruction.Create(type)); } - public void EmitOr(Type type) { - Emit(OrInstruction.Create(type)); + public void EmitOr(Type type, bool lifted) { + Emit(lifted ? OrInstruction.CreateLifted(type) : OrInstruction.Create(type)); } - public void EmitAnd(Type type) { - Emit(AndInstruction.Create(type)); + public void EmitAnd(Type type, bool lifted) { + Emit(lifted ? AndInstruction.CreateLifted (type) : AndInstruction.Create(type)); } - public void EmitExclusiveOr(Type type) { - Emit(XorInstruction.Create(type)); + public void EmitExclusiveOr(Type type, bool lifted) { + Emit(lifted ? XorInstruction.CreateLifted(type) : XorInstruction.Create(type)); } #region Comparisons - public void EmitEqual(Type type) { - Emit(EqualInstruction.Create(type)); + public void EmitEqual(Type type, bool liftedResult) { + Emit(liftedResult ? + EqualInstruction.CreateLifted(TypeUtils.GetNonNullableType (type)) : + EqualInstruction.Create(TypeUtils.GetNonNullableType (type))); } - public void EmitNotEqual(Type type) { - Emit(NotEqualInstruction.Create(type)); + public void EmitNotEqual(Type type, bool liftedResult) { + Emit(liftedResult ? + NotEqualInstruction.CreateLifted(TypeUtils.GetNonNullableType (type)) : + NotEqualInstruction.Create(TypeUtils.GetNonNullableType (type))); } - public void EmitLessThan(Type type) { - Emit(LessThanInstruction.Create(type)); + public void EmitLessThan(Type type, bool liftedResult) { + Emit(liftedResult ? + LessThanInstruction.CreateLifted(TypeUtils.GetNonNullableType (type)) : + LessThanInstruction.Create(TypeUtils.GetNonNullableType (type))); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")] - public void EmitLessThanOrEqual(Type type) { - throw new NotSupportedException(); + public void EmitLessThanOrEqual(Type type, bool liftedResult) { + Emit(liftedResult ? + LessThanOrEqualInstruction.CreateLifted(TypeUtils.GetNonNullableType (type)) : + LessThanOrEqualInstruction.Create(TypeUtils.GetNonNullableType (type))); } - public void EmitGreaterThan(Type type) { - Emit(GreaterThanInstruction.Create(type)); + public void EmitGreaterThan(Type type, bool liftedResult) { + Emit(liftedResult ? + GreaterThanInstruction.CreateLifted(TypeUtils.GetNonNullableType (type)) : + GreaterThanInstruction.Create(TypeUtils.GetNonNullableType (type))); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters")] - public void EmitGreaterThanOrEqual(Type type) { - throw new NotSupportedException(); + public void EmitGreaterThanOrEqual(Type type, bool liftedResult) { + Emit(liftedResult ? + GreaterThanOrEqualInstruction.CreateLifted(TypeUtils.GetNonNullableType (type)) : + GreaterThanOrEqualInstruction.Create(TypeUtils.GetNonNullableType (type))); } #endregion @@ -728,15 +738,24 @@ namespace Microsoft.Scripting.Interpreter { #region Unary Operators - public void EmitNegate(Type type, bool @checked) { + public void EmitNegate(Type type, bool @checked, bool lifted) { if (@checked) - Emit(NegateOvfInstruction.Create(type)); + Emit(lifted ? NegateOvfInstruction.CreateLifted(type) : NegateOvfInstruction.Create(type)); else - Emit(NegateInstruction.Create(type)); + Emit(lifted ? NegateInstruction.CreateLifted(type) : NegateInstruction.Create(type)); } - public void EmitNot(Type type) { - Emit(NotInstruction.Create(type)); + public void EmitNot(Type type, bool lifted) { + Emit(lifted ? NotInstruction.CreateLifted (type) : NotInstruction.Create(type)); + } + + #endregion + + #region Nullable operations + + public void EmitWrap (Type elementType) + { + Emit(InstructionFactory.GetFactory(elementType).WrapToNullable (elementType)); } #endregion @@ -989,6 +1008,10 @@ namespace Microsoft.Scripting.Interpreter { EmitBranch(new BranchFalseInstruction(), elseLabel); } + public void EmitBranchNull(BranchLabel elseLabel) { + EmitBranch(new BranchNullInstruction(), elseLabel); + } + public void EmitThrow() { Emit(ThrowInstruction.Throw); } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanInstruction.cs index 2875e8bf9cd..3bde7a4ee8f 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanInstruction.cs @@ -1,17 +1,30 @@ -/* **************************************************************************** - * - * Copyright (c) Microsoft Corporation. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. A - * copy of the license can be found in the License.html file at the root of this distribution. If - * you cannot locate the Apache License, Version 2.0, please send an email to - * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound - * by the terms of the Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - * - * - * ***************************************************************************/ +// +// LessThanInstruction.cs: +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Copyright 2014 Xamarin Inc +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// using System; using System.Collections.Generic; @@ -24,6 +37,7 @@ using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { public abstract class LessThanInstruction : Instruction { private static Instruction _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double; + private static Instruction _SByteLifted, _Int16Lifted, _CharLifted, _Int32Lifted, _Int64Lifted, _ByteLifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _SingleLifted, _DoubleLifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -31,90 +45,158 @@ namespace Microsoft.Scripting.Interpreter { private LessThanInstruction() { } + public bool LiftedToNull { get; set; } + internal sealed class LessThanSByte : LessThanInstruction { public override int Run(InterpretedFrame frame) { - SByte right = (SByte)frame.Pop(); - frame.Push(((SByte)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (SByte)l < (SByte)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanInt16 : LessThanInstruction { public override int Run(InterpretedFrame frame) { - Int16 right = (Int16)frame.Pop(); - frame.Push(((Int16)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int16)l < (Int16)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanChar : LessThanInstruction { public override int Run(InterpretedFrame frame) { - Char right = (Char)frame.Pop(); - frame.Push(((Char)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Char)l < (Char)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanInt32 : LessThanInstruction { public override int Run(InterpretedFrame frame) { - Int32 right = (Int32)frame.Pop(); - frame.Push(((Int32)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int32)l < (Int32)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanInt64 : LessThanInstruction { public override int Run(InterpretedFrame frame) { - Int64 right = (Int64)frame.Pop(); - frame.Push(((Int64)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int64)l < (Int64)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanByte : LessThanInstruction { public override int Run(InterpretedFrame frame) { - Byte right = (Byte)frame.Pop(); - frame.Push(((Byte)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Byte)l < (Byte)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanUInt16 : LessThanInstruction { public override int Run(InterpretedFrame frame) { - UInt16 right = (UInt16)frame.Pop(); - frame.Push(((UInt16)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt16)l < (UInt16)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanUInt32 : LessThanInstruction { public override int Run(InterpretedFrame frame) { - UInt32 right = (UInt32)frame.Pop(); - frame.Push(((UInt32)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt32)l < (UInt32)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanUInt64 : LessThanInstruction { public override int Run(InterpretedFrame frame) { - UInt64 right = (UInt64)frame.Pop(); - frame.Push(((UInt64)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt64)l < (UInt64)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanSingle : LessThanInstruction { public override int Run(InterpretedFrame frame) { - Single right = (Single)frame.Pop(); - frame.Push(((Single)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Single)l < (Single)r; + + frame.StackIndex--; return +1; } } internal sealed class LessThanDouble : LessThanInstruction { public override int Run(InterpretedFrame frame) { - Double right = (Double)frame.Pop(); - frame.Push(((Double)frame.Pop()) < right); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Double)l < (Double)r; + + frame.StackIndex--; return +1; } } @@ -139,6 +221,26 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.SByte: return _SByteLifted ?? (_SByteLifted = new LessThanSByte() { LiftedToNull = true }); + case TypeCode.Byte: return _ByteLifted ?? (_ByteLifted = new LessThanByte() { LiftedToNull = true }); + case TypeCode.Char: return _CharLifted ?? (_CharLifted = new LessThanChar() { LiftedToNull = true }); + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new LessThanInt16() { LiftedToNull = true }); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new LessThanInt32() { LiftedToNull = true }); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new LessThanInt64() { LiftedToNull = true }); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new LessThanUInt16() { LiftedToNull = true }); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new LessThanUInt32() { LiftedToNull = true }); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new LessThanUInt64() { LiftedToNull = true }); + case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new LessThanSingle() { LiftedToNull = true }); + case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new LessThanDouble() { LiftedToNull = true }); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "LessThan()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanOrEqualInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanOrEqualInstruction.cs new file mode 100644 index 00000000000..6c120f59349 --- /dev/null +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/LessThanOrEqualInstruction.cs @@ -0,0 +1,248 @@ +// +// LessThanOrEqualInstruction.cs: +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Copyright 2014 Xamarin Inc +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.CompilerServices; +using Microsoft.Scripting.Runtime; +using Microsoft.Scripting.Utils; + +namespace Microsoft.Scripting.Interpreter { + public abstract class LessThanOrEqualInstruction : Instruction { + private static Instruction _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double; + private static Instruction _SByteLifted, _Int16Lifted, _CharLifted, _Int32Lifted, _Int64Lifted, _ByteLifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _SingleLifted, _DoubleLifted; + + public override int ConsumedStack { get { return 2; } } + public override int ProducedStack { get { return 1; } } + + private LessThanOrEqualInstruction() { + } + + public bool LiftedToNull { get; set; } + + internal sealed class LessThanOrEqualSByte : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (SByte)l <= (SByte)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualInt16 : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int16)l <= (Int16)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualChar : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Char)l <= (Char)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualInt32 : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int32)l <= (Int32)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualInt64 : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Int64)l <= (Int64)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualByte : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Byte)l <= (Byte)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualUInt16 : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt16)l <= (UInt16)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualUInt32 : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt32)l <= (UInt32)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualUInt64 : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (UInt64)l <= (UInt64)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualSingle : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Single)l <= (Single)r; + + frame.StackIndex--; + return +1; + } + } + + internal sealed class LessThanOrEqualDouble : LessThanOrEqualInstruction { + public override int Run(InterpretedFrame frame) { + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) false; + else + frame.Data[frame.StackIndex - 2] = (Double)l <= (Double)r; + + frame.StackIndex--; + return +1; + } + } + + public static Instruction Create(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.SByte: return _SByte ?? (_SByte = new LessThanOrEqualSByte()); + case TypeCode.Byte: return _Byte ?? (_Byte = new LessThanOrEqualByte()); + case TypeCode.Char: return _Char ?? (_Char = new LessThanOrEqualChar()); + case TypeCode.Int16: return _Int16 ?? (_Int16 = new LessThanOrEqualInt16()); + case TypeCode.Int32: return _Int32 ?? (_Int32 = new LessThanOrEqualInt32()); + case TypeCode.Int64: return _Int64 ?? (_Int64 = new LessThanOrEqualInt64()); + case TypeCode.UInt16: return _UInt16 ?? (_UInt16 = new LessThanOrEqualUInt16()); + case TypeCode.UInt32: return _UInt32 ?? (_UInt32 = new LessThanOrEqualUInt32()); + case TypeCode.UInt64: return _UInt64 ?? (_UInt64 = new LessThanOrEqualUInt64()); + case TypeCode.Single: return _Single ?? (_Single = new LessThanOrEqualSingle()); + case TypeCode.Double: return _Double ?? (_Double = new LessThanOrEqualDouble()); + + default: + throw Assert.Unreachable; + } + } + + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.SByte: return _SByteLifted ?? (_SByteLifted = new LessThanOrEqualSByte() { LiftedToNull = true }); + case TypeCode.Byte: return _ByteLifted ?? (_ByteLifted = new LessThanOrEqualByte() { LiftedToNull = true }); + case TypeCode.Char: return _CharLifted ?? (_CharLifted = new LessThanOrEqualChar() { LiftedToNull = true }); + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new LessThanOrEqualInt16() { LiftedToNull = true }); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new LessThanOrEqualInt32() { LiftedToNull = true }); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new LessThanOrEqualInt64() { LiftedToNull = true }); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new LessThanOrEqualUInt16() { LiftedToNull = true }); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new LessThanOrEqualUInt32() { LiftedToNull = true }); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new LessThanOrEqualUInt64() { LiftedToNull = true }); + case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new LessThanOrEqualSingle() { LiftedToNull = true }); + case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new LessThanOrEqualDouble() { LiftedToNull = true }); + + default: + throw Assert.Unreachable; + } + } + + public override string ToString() { + return "LessThanOrEqual()"; + } + } +} diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/MulInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/MulInstruction.cs index 4529adc4512..745e1a0bcad 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/MulInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/MulInstruction.cs @@ -166,7 +166,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int16)checked((Int16)l * (Int16)r); + frame.Data[frame.StackIndex - 2] = checked((Int16)((Int16)l * (Int16)r)); frame.StackIndex--; return +1; } @@ -176,7 +176,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int64)checked((Int64)l * (Int64)r); + frame.Data[frame.StackIndex - 2] = checked((Int64)((Int64)l * (Int64)r)); frame.StackIndex--; return +1; } @@ -186,7 +186,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt16)checked((UInt16)l * (UInt16)r); + frame.Data[frame.StackIndex - 2] = checked((UInt16)((UInt16)l * (UInt16)r)); frame.StackIndex--; return +1; } @@ -196,7 +196,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt32)checked((UInt32)l * (UInt32)r); + frame.Data[frame.StackIndex - 2] = checked((UInt32)((UInt32)l * (UInt32)r)); frame.StackIndex--; return +1; } @@ -206,7 +206,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt64)checked((UInt64)l * (UInt64)r); + frame.Data[frame.StackIndex - 2] = checked((UInt64)((UInt64)l * (UInt64)r)); frame.StackIndex--; return +1; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NegateInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NegateInstruction.cs index 58c60f6803b..5652f5bc78b 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NegateInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NegateInstruction.cs @@ -34,6 +34,7 @@ using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { internal abstract class NegateInstruction : Instruction { private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _Single, _Double; + private static Instruction _Int16Lifted, _Int32Lifted, _Int64Lifted, _UInt16Lifted, _UInt32Lifted, _SingleLifted, _DoubleLifted; public override int ConsumedStack { get { return 1; } } public override int ProducedStack { get { return 1; } } @@ -43,7 +44,7 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateInt32 : NegateInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; + var v = frame.Data[frame.StackIndex - 1]; frame.Data[frame.StackIndex - 1] = ScriptingRuntimeHelpers.Int32ToObject(unchecked(-(Int32)v)); return 1; } @@ -51,24 +52,24 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateInt16 : NegateInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Int16)unchecked(-(Int16)v); + var v = (Int16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int16)unchecked(-v); return 1; } } internal sealed class NegateInt64 : NegateInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Int64)unchecked(-(Int64)v); + var v = (Int64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int64)unchecked(-v); return 1; } } internal sealed class NegateUInt16 : NegateInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (UInt16)unchecked(-(UInt16)v); + var v = (UInt16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt16)unchecked(-v); return 1; } @@ -76,8 +77,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateUInt32 : NegateInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (UInt32)unchecked(-(UInt32)v); + var v = (UInt32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt32)unchecked(-v); return 1; } @@ -85,8 +86,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateSingle : NegateInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Single)unchecked(-(Single)v); + var v = (Single)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Single)unchecked(-v); return 1; } @@ -94,8 +95,68 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateDouble : NegateInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Double)unchecked(-(Double)v); + var v = (Double)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Double)unchecked(-v); + return 1; + + } + } + + internal sealed class NegateInt32Lifted : NegateInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int32?)(unchecked(-v)); + return 1; + } + } + + internal sealed class NegateInt16Lifted : NegateInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int16?)unchecked(-v); + return 1; + } + } + + internal sealed class NegateInt64Lifted : NegateInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int64?)unchecked(-v); + return 1; + } + } + + internal sealed class NegateUInt16Lifted : NegateInstruction { + public override int Run(InterpretedFrame frame) { + var v = (UInt16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt16?)unchecked(-v); + return 1; + + } + } + + internal sealed class NegateUInt32Lifted : NegateInstruction { + public override int Run(InterpretedFrame frame) { + var v = (UInt32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt32?)unchecked(-v); + return 1; + + } + } + + internal sealed class NegateSingleLifted : NegateInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Single?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Single?)unchecked(-v); + return 1; + + } + } + + internal sealed class NegateDoubleLifted : NegateInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Double?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Double?)unchecked(-v); return 1; } @@ -117,6 +178,22 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new NegateInt16Lifted()); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new NegateInt32Lifted()); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new NegateInt64Lifted()); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new NegateUInt16Lifted()); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new NegateUInt32Lifted()); + case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new NegateSingleLifted()); + case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new NegateDoubleLifted()); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "Negate()"; } @@ -124,6 +201,7 @@ namespace Microsoft.Scripting.Interpreter { internal abstract class NegateOvfInstruction : Instruction { private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _Single, _Double; + private static Instruction _Int16Lifted, _Int32Lifted, _Int64Lifted, _UInt16Lifted, _UInt32Lifted, _SingleLifted, _DoubleLifted; public override int ConsumedStack { get { return 1; } } public override int ProducedStack { get { return 1; } } @@ -133,32 +211,32 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateOvfInt32 : NegateOvfInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = ScriptingRuntimeHelpers.Int32ToObject(checked(-(Int32)v)); + var v = (Int32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = ScriptingRuntimeHelpers.Int32ToObject(checked(-v)); return 1; } } internal sealed class NegateOvfInt16 : NegateOvfInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Int16)checked(-(Int16)v); + var v = (Int16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = checked((Int16)(-v)); return 1; } } internal sealed class NegateOvfInt64 : NegateOvfInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Int64)checked(-(Int64)v); + var v = (Int64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = checked((Int64)(-v)); return 1; } } internal sealed class NegateOvfUInt16 : NegateOvfInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (UInt16)checked(-(UInt16)v); + var v = (UInt16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = checked((UInt16)(-v)); return 1; } @@ -166,8 +244,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateOvfUInt32 : NegateOvfInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (UInt32)checked(-(UInt32)v); + var v = (UInt32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = checked((UInt32)(-v)); return 1; } @@ -175,8 +253,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateOvfSingle : NegateOvfInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Single)checked(-(Single)v); + var v = (Single)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Single)checked(-v); return 1; } @@ -184,8 +262,68 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NegateOvfDouble : NegateOvfInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Double)checked(-(Double)v); + var v = (Double)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Double)checked(-v); + return 1; + + } + } + + internal sealed class NegateOvfInt32Lifted : NegateOvfInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int32?)(unchecked(-v)); + return 1; + } + } + + internal sealed class NegateOvfInt16Lifted : NegateOvfInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int16?)unchecked(-v); + return 1; + } + } + + internal sealed class NegateOvfInt64Lifted : NegateOvfInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int64?)unchecked(-v); + return 1; + } + } + + internal sealed class NegateOvfUInt16Lifted : NegateOvfInstruction { + public override int Run(InterpretedFrame frame) { + var v = (UInt16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt16?)unchecked(-v); + return 1; + + } + } + + internal sealed class NegateOvfUInt32Lifted : NegateOvfInstruction { + public override int Run(InterpretedFrame frame) { + var v = (UInt32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt32?)unchecked(-v); + return 1; + + } + } + + internal sealed class NegateOvfSingleLifted : NegateOvfInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Single?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Single?)unchecked(-v); + return 1; + + } + } + + internal sealed class NegateOvfDoubleLifted : NegateOvfInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Double?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Double?)unchecked(-v); return 1; } @@ -207,6 +345,22 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new NegateOvfInt16Lifted()); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new NegateOvfInt32Lifted()); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new NegateOvfInt64Lifted()); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new NegateOvfUInt16Lifted()); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new NegateOvfUInt32Lifted()); + case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new NegateOvfSingleLifted()); + case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new NegateOvfDoubleLifted()); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "NegateOvf()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotEqualInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotEqualInstruction.cs index f7da9f46dd3..2bd1224374f 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotEqualInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotEqualInstruction.cs @@ -25,6 +25,8 @@ namespace Microsoft.Scripting.Interpreter { internal abstract class NotEqualInstruction : Instruction { // Perf: EqualityComparer<T> but is 3/2 to 2 times slower. private static Instruction _Reference, _Boolean, _SByte, _Int16, _Char, _Int32, _Int64, _Byte, _UInt16, _UInt32, _UInt64, _Single, _Double; + private static Instruction _BooleanLifted, _SByteLifted, _Int16Lifted, _CharLifted, _Int32Lifted, _Int64Lifted, + _ByteLifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _SingleLifted, _DoubleLifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -32,86 +34,171 @@ namespace Microsoft.Scripting.Interpreter { private NotEqualInstruction() { } + public bool LiftedToNull { get; set; } + internal sealed class NotEqualBoolean : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Boolean)frame.Pop()) != ((Boolean)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (Boolean)l != (Boolean)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualSByte : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((SByte)frame.Pop()) != ((SByte)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (SByte)l != (SByte)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualInt16 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Int16)frame.Pop()) != ((Int16)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (Int16)l != (Int16)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualChar : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Char)frame.Pop()) != ((Char)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (Char)l != (Char)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualInt32 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Int32)frame.Pop()) != ((Int32)frame.Pop())); - return +1; - } + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (Int32)l != (Int32)r; + + frame.StackIndex--; + return +1; } } internal sealed class NotEqualInt64 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Int64)frame.Pop()) != ((Int64)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (Int64)l != (Int64)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualByte : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Byte)frame.Pop()) != ((Byte)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (Byte)l != (Byte)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualUInt16 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((UInt16)frame.Pop()) != ((UInt16)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (UInt16)l != (UInt16)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualUInt32 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((UInt32)frame.Pop()) != ((UInt32)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (UInt32)l != (UInt32)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualUInt64 : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((UInt64)frame.Pop()) != ((UInt64)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (UInt64)l != (UInt64)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualSingle : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Single)frame.Pop()) != ((Single)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (Single)l != (Single)r; + + frame.StackIndex--; return +1; } } internal sealed class NotEqualDouble : NotEqualInstruction { public override int Run(InterpretedFrame frame) { - frame.Push(((Double)frame.Pop()) != ((Double)frame.Pop())); + object l = frame.Data[frame.StackIndex - 2]; + object r = frame.Data[frame.StackIndex - 1]; + if (l == null || r == null) + frame.Data[frame.StackIndex - 2] = LiftedToNull ? (object) null : (object) l != r; + else + frame.Data[frame.StackIndex - 2] = (Double)l != (Double)r; + + frame.StackIndex--; return +1; } } @@ -154,6 +241,29 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + // Boxed enums can be unboxed as their underlying types: + switch ((type.IsEnum() ? Enum.GetUnderlyingType(type) : type).GetTypeCode()) { + case TypeCode.Boolean: return _BooleanLifted ?? (_BooleanLifted = new NotEqualBoolean() { LiftedToNull = true }); + case TypeCode.SByte: return _SByteLifted ?? (_SByteLifted = new NotEqualSByte() { LiftedToNull = true }); + case TypeCode.Byte: return _ByteLifted ?? (_ByteLifted = new NotEqualByte() { LiftedToNull = true }); + case TypeCode.Char: return _CharLifted ?? (_CharLifted = new NotEqualChar() { LiftedToNull = true }); + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new NotEqualInt16() { LiftedToNull = true }); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new NotEqualInt32() { LiftedToNull = true }); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new NotEqualInt64() { LiftedToNull = true }); + + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new NotEqualInt16() { LiftedToNull = true }); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new NotEqualInt32() { LiftedToNull = true }); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new NotEqualInt64() { LiftedToNull = true }); + + case TypeCode.Single: return _SingleLifted ?? (_SingleLifted = new NotEqualSingle() { LiftedToNull = true }); + case TypeCode.Double: return _DoubleLifted ?? (_DoubleLifted = new NotEqualDouble() { LiftedToNull = true }); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "NotEqual()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotInstruction.cs index 3cfce546518..e1eb3d8bd11 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/NotInstruction.cs @@ -34,6 +34,7 @@ using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { internal abstract class NotInstruction : Instruction { private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64, _Boolean; + private static Instruction _Int16Lifted, _Int32Lifted, _Int64Lifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _BooleanLifted; public override int ConsumedStack { get { return 1; } } public override int ProducedStack { get { return 1; } } @@ -50,48 +51,104 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class NotInt32 : NotInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = ScriptingRuntimeHelpers.Int32ToObject(~(Int32)v); + var v = (Int32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = ScriptingRuntimeHelpers.Int32ToObject(~v); return 1; } } internal sealed class NotInt16 : NotInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Int16)(~(Int16)v); + var v = (Int16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int16)(~v); return 1; } } internal sealed class NotInt64 : NotInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (Int64)(~(Int64)v); + var v = (Int64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int64)(~v); return 1; } } internal sealed class NotUInt16 : NotInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (UInt64)(~(UInt64)v); + var v = (UInt64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt64)(~v); return 1; } } internal sealed class NotUInt32 : NotInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (UInt32)(~(UInt32)v); + var v = (UInt32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt32)(~v); return 1; } } internal sealed class NotUInt64 : NotInstruction { public override int Run(InterpretedFrame frame) { - object v = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 1] = (UInt64)(~(UInt64)v); + var v = (UInt64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt64)(~v); + return 1; + } + } + + internal sealed class NotBooleanLifted : NotInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Boolean?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Boolean?)(!v); + return 1; + } + } + + internal sealed class NotInt32Lifted : NotInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int32?)(~v); + return 1; + } + } + + internal sealed class NotInt16Lifted : NotInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int16?)(~v); + return 1; + } + } + + internal sealed class NotInt64Lifted : NotInstruction { + public override int Run(InterpretedFrame frame) { + var v = (Int64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (Int64?)(~v); + return 1; + } + } + + internal sealed class NotUInt16Lifted : NotInstruction { + public override int Run(InterpretedFrame frame) { + var v = (UInt64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt64?)(~v); + return 1; + } + } + + internal sealed class NotUInt32Lifted : NotInstruction { + public override int Run(InterpretedFrame frame) { + var v = (UInt32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt32?)(~v); + return 1; + } + } + + internal sealed class NotUInt64Lifted : NotInstruction { + public override int Run(InterpretedFrame frame) { + var v = (UInt64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 1] = (UInt64?)(~v); return 1; } } @@ -112,6 +169,21 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new NotInt16Lifted()); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new NotInt32Lifted()); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new NotInt64Lifted()); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new NotUInt16Lifted()); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new NotUInt32Lifted()); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new NotUInt64Lifted()); + case TypeCode.Boolean: return _BooleanLifted ?? (_BooleanLifted = new NotBooleanLifted()); + + default: + throw Assert.Unreachable; + } + } public override string ToString() { return "Not()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/OrInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/OrInstruction.cs index b183b689042..baaad40fb70 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/OrInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/OrInstruction.cs @@ -34,6 +34,7 @@ using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { internal abstract class OrInstruction : Instruction { private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64, _Boolean; + private static Instruction _Int16Lifted, _Int32Lifted, _Int64Lifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _BooleanLifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -43,8 +44,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class OrInt32 : OrInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; + var l = frame.Data[frame.StackIndex - 2]; + var r = frame.Data[frame.StackIndex - 1]; frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject((Int32)l | (Int32)r); frame.StackIndex--; return 1; @@ -53,8 +54,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class OrInt16 : OrInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; + var l = frame.Data[frame.StackIndex - 2]; + var r = frame.Data[frame.StackIndex - 1]; frame.Data[frame.StackIndex - 2] = (Int16)((Int16)l | (Int16)r); frame.StackIndex--; return 1; @@ -63,8 +64,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class OrInt64 : OrInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; + var l = frame.Data[frame.StackIndex - 2]; + var r = frame.Data[frame.StackIndex - 1]; frame.Data[frame.StackIndex - 2] = (Int64)((Int64)l | (Int64)r); frame.StackIndex--; return 1; @@ -73,8 +74,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class OrUInt16 : OrInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; + var l = frame.Data[frame.StackIndex - 2]; + var r = frame.Data[frame.StackIndex - 1]; frame.Data[frame.StackIndex - 2] = (UInt16)((UInt16)l | (UInt16)r); frame.StackIndex--; return 1; @@ -83,8 +84,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class OrUInt32 : OrInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; + var l = frame.Data[frame.StackIndex - 2]; + var r = frame.Data[frame.StackIndex - 1]; frame.Data[frame.StackIndex - 2] = (UInt32)((UInt32)l | (UInt32)r); frame.StackIndex--; return 1; @@ -93,8 +94,8 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class OrUInt64 : OrInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; + var l = frame.Data[frame.StackIndex - 2]; + var r = frame.Data[frame.StackIndex - 1]; frame.Data[frame.StackIndex - 2] = (UInt64)((UInt64)l | (UInt64)r); frame.StackIndex--; return 1; @@ -103,14 +104,84 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class OrBoolean : OrInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; + var l = frame.Data[frame.StackIndex - 2]; + var r = frame.Data[frame.StackIndex - 1]; frame.Data[frame.StackIndex - 2] = (Boolean)((Boolean)l | (Boolean)r); frame.StackIndex--; return 1; } } + internal sealed class OrInt32Lifted : OrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int32?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32?)(l | r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class OrInt16Lifted : OrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int16?)frame.Data[frame.StackIndex - 2]; + var r = (Int16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int16?)(l | r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class OrInt64Lifted : OrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int64?)frame.Data[frame.StackIndex - 2]; + var r = (Int64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int64?)(l | r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class OrUInt16Lifted : OrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt16?)frame.Data[frame.StackIndex - 2]; + var r = (UInt16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt16?)(l | r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class OrUInt32Lifted : OrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt32?)frame.Data[frame.StackIndex - 2]; + var r = (UInt32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt32?)(l | r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class OrUInt64Lifted : OrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt64?)frame.Data[frame.StackIndex - 2]; + var r = (UInt64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt64?)(l | r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class OrBooleanLifted : OrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Boolean?)frame.Data[frame.StackIndex - 2]; + var r = (Boolean?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Boolean?)(l | r); + frame.StackIndex--; + return 1; + } + } + public static Instruction Create(Type type) { Debug.Assert(!type.IsEnum()); switch (type.GetTypeCode()) { @@ -127,6 +198,22 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new OrInt16Lifted()); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new OrInt32Lifted()); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new OrInt64Lifted()); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new OrUInt16Lifted()); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new OrUInt32Lifted()); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new OrUInt64Lifted()); + case TypeCode.Boolean: return _BooleanLifted ?? (_BooleanLifted = new OrBooleanLifted()); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "Or()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ShlInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ShlInstruction.cs index 4db455315ab..5406dd01b00 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ShlInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ShlInstruction.cs @@ -34,6 +34,7 @@ using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { internal abstract class ShlInstruction : Instruction { private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64; + private static Instruction _Int16Lifted, _Int32Lifted, _Int64Lifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -101,6 +102,66 @@ namespace Microsoft.Scripting.Interpreter { } } + internal sealed class ShlInt32Lifted : ShlInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int32?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32?)(l << r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShlInt16Lifted : ShlInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int16?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32)(l << r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShlInt64Lifted : ShlInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int64?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int64?)(l << r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShlUInt16Lifted : ShlInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt16?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32?)(l << r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShlUInt32Lifted : ShlInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt32?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt32?)(l << r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShlUInt64Lifted : ShlInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt64?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt64?)(l << r); + frame.StackIndex--; + return 1; + } + } + public static Instruction Create(Type type) { Debug.Assert(!type.IsEnum()); switch (type.GetTypeCode()) { @@ -116,6 +177,21 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new ShlInt16Lifted()); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new ShlInt32Lifted()); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new ShlInt64Lifted()); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new ShlUInt16Lifted()); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new ShlUInt32Lifted()); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new ShlUInt64Lifted()); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "Shl()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ShrInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ShrInstruction.cs index cefb800f17b..5099a41c18b 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ShrInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/ShrInstruction.cs @@ -34,6 +34,7 @@ using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { internal abstract class ShrInstruction : Instruction { private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64; + private static Instruction _Int16Lifted, _Int32Lifted, _Int64Lifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -101,6 +102,66 @@ namespace Microsoft.Scripting.Interpreter { } } + internal sealed class ShrInt32Lifted : ShrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int32?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32?)(l >> r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShrInt16Lifted : ShrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int16?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32)(l >> r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShrInt64Lifted : ShrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int64?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int64?)(l >> r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShrUInt16Lifted : ShrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt16?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32?)(l >> r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShrUInt32Lifted : ShrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt32?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt32?)(l >> r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class ShrUInt64Lifted : ShrInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt64?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt64?)(l >> r); + frame.StackIndex--; + return 1; + } + } + public static Instruction Create(Type type) { Debug.Assert(!type.IsEnum()); switch (type.GetTypeCode()) { @@ -116,6 +177,21 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new ShrInt16Lifted()); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new ShrInt32Lifted()); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new ShrInt64Lifted()); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new ShrUInt16Lifted()); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new ShrUInt32Lifted()); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new ShrUInt64Lifted()); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "Shr()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/StackOperations.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/StackOperations.cs index e2c9e7d1ab7..6cff464f0aa 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/StackOperations.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/StackOperations.cs @@ -106,7 +106,8 @@ namespace Microsoft.Scripting.Interpreter { public override int ProducedStack { get { return 1; } } public override int Run(InterpretedFrame frame) { - frame.Data[frame.StackIndex++] = frame.Peek(); + frame.Data[frame.StackIndex] = frame.Peek(); + frame.StackIndex++; return +1; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/SubInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/SubInstruction.cs index 4571e4f930e..8ca97e97f7e 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/SubInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/SubInstruction.cs @@ -166,7 +166,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int16)checked((Int16)l - (Int16)r); + frame.Data[frame.StackIndex - 2] = checked((Int16)((Int16)l - (Int16)r)); frame.StackIndex--; return +1; } @@ -176,7 +176,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int64)checked((Int64)l - (Int64)r); + frame.Data[frame.StackIndex - 2] = checked((Int64)((Int64)l - (Int64)r)); frame.StackIndex--; return +1; } @@ -186,7 +186,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt16)checked((UInt16)l - (UInt16)r); + frame.Data[frame.StackIndex - 2] = checked((UInt16)((UInt16)l - (UInt16)r)); frame.StackIndex--; return +1; } @@ -196,7 +196,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt32)checked((UInt32)l - (UInt32)r); + frame.Data[frame.StackIndex - 2] = checked((UInt32)((UInt32)l - (UInt32)r)); frame.StackIndex--; return +1; } @@ -206,7 +206,7 @@ namespace Microsoft.Scripting.Interpreter { public override int Run(InterpretedFrame frame) { object l = frame.Data[frame.StackIndex - 2]; object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt64)checked((UInt64)l - (UInt64)r); + frame.Data[frame.StackIndex - 2] = checked((UInt64)((UInt64)l - (UInt64)r)); frame.StackIndex--; return +1; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/TypeOperations.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/TypeOperations.cs index 320deb5b3a6..44354f7f41b 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/TypeOperations.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/TypeOperations.cs @@ -20,6 +20,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using Microsoft.Scripting.Runtime; using Microsoft.Scripting.Utils; +using System.Linq; namespace Microsoft.Scripting.Interpreter { internal sealed class CreateDelegateInstruction : Instruction { @@ -160,4 +161,33 @@ namespace Microsoft.Scripting.Interpreter { get { return "TypeEquals()"; } } } + + internal sealed class WrapToNullableInstruction<T> : Instruction { + + readonly Type elementType; + ConstructorInfo ctor; + + public override int ConsumedStack { get { return 1; } } + public override int ProducedStack { get { return 1; } } + + internal WrapToNullableInstruction(Type elementType) { + this.elementType = elementType; + } + + public override int Run(InterpretedFrame frame) { + var r = frame.Data[frame.StackIndex - 1]; + + // Don't need to wrap null values + if (r == null) + return 1; + + ctor = typeof (Nullable<>).MakeGenericType (elementType).GetDeclaredConstructors ().First (); + frame.Data[frame.StackIndex - 1] = ctor.Invoke (new [] { r }); + return 1; + } + + public override string InstructionName { + get { return "WrapTo " + typeof(T) + "?"; } + } + } } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/XorInstruction.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/XorInstruction.cs index 37360a8beed..21f285c02e6 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/XorInstruction.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/XorInstruction.cs @@ -1,5 +1,5 @@ // -// AndbInstruction.cs: +// XorInstruction.cs: // // Authors: Marek Safar (marek.safar@gmail.com) // @@ -34,6 +34,7 @@ using Microsoft.Scripting.Utils; namespace Microsoft.Scripting.Interpreter { internal abstract class XorInstruction : Instruction { private static Instruction _Int16, _Int32, _Int64, _UInt16, _UInt32, _UInt64, _Boolean; + private static Instruction _Int16Lifted, _Int32Lifted, _Int64Lifted, _UInt16Lifted, _UInt32Lifted, _UInt64Lifted, _BooleanLifted; public override int ConsumedStack { get { return 2; } } public override int ProducedStack { get { return 1; } } @@ -43,9 +44,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class XorInt32 : XorInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject((Int32)l ^ (Int32)r); + var l = (Int32)frame.Data[frame.StackIndex - 2]; + var r = (Int32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = ScriptingRuntimeHelpers.Int32ToObject(l ^ r); frame.StackIndex--; return 1; } @@ -53,9 +54,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class XorInt16 : XorInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int16)((Int16)l ^ (Int16)r); + var l = (Int16)frame.Data[frame.StackIndex - 2]; + var r = (Int16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int16)(l ^ r); frame.StackIndex--; return 1; } @@ -63,9 +64,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class XorInt64 : XorInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Int64)((Int64)l ^ (Int64)r); + var l = (Int64)frame.Data[frame.StackIndex - 2]; + var r = (Int64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int64)(l ^ r); frame.StackIndex--; return 1; } @@ -73,9 +74,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class XorUInt16 : XorInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt16)((UInt16)l ^ (UInt16)r); + var l = (UInt16)frame.Data[frame.StackIndex - 2]; + var r = (UInt16)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt16)(l ^ r); frame.StackIndex--; return 1; } @@ -83,9 +84,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class XorUInt32 : XorInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt32)((UInt32)l ^ (UInt32)r); + var l = (UInt32)frame.Data[frame.StackIndex - 2]; + var r = (UInt32)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt32)(l ^ r); frame.StackIndex--; return 1; } @@ -93,9 +94,9 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class XorUInt64 : XorInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (UInt64)((UInt64)l ^ (UInt64)r); + var l = (UInt64)frame.Data[frame.StackIndex - 2]; + var r = (UInt64)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt64)(l ^ r); frame.StackIndex--; return 1; } @@ -103,9 +104,79 @@ namespace Microsoft.Scripting.Interpreter { internal sealed class XorBoolean : XorInstruction { public override int Run(InterpretedFrame frame) { - object l = frame.Data[frame.StackIndex - 2]; - object r = frame.Data[frame.StackIndex - 1]; - frame.Data[frame.StackIndex - 2] = (Boolean)((Boolean)l ^ (Boolean)r); + var l = (Boolean)frame.Data[frame.StackIndex - 2]; + var r = (Boolean)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Boolean)(l ^ r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class XorInt32Lifted : XorInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int32?)frame.Data[frame.StackIndex - 2]; + var r = (Int32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int32?)(l ^ r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class XorInt16Lifted : XorInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int16?)frame.Data[frame.StackIndex - 2]; + var r = (Int16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int16?)(l ^ r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class XorInt64Lifted : XorInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Int64?)frame.Data[frame.StackIndex - 2]; + var r = (Int64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Int64?)(l ^ r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class XorUInt16Lifted : XorInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt16?)frame.Data[frame.StackIndex - 2]; + var r = (UInt16?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt16?)(l ^ r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class XorUInt32Lifted : XorInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt32?)frame.Data[frame.StackIndex - 2]; + var r = (UInt32?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt32?)(l ^ r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class XorUInt64Lifted : XorInstruction { + public override int Run(InterpretedFrame frame) { + var l = (UInt64?)frame.Data[frame.StackIndex - 2]; + var r = (UInt64?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (UInt64?)(l ^ r); + frame.StackIndex--; + return 1; + } + } + + internal sealed class XorBooleanLifted : XorInstruction { + public override int Run(InterpretedFrame frame) { + var l = (Boolean?)frame.Data[frame.StackIndex - 2]; + var r = (Boolean?)frame.Data[frame.StackIndex - 1]; + frame.Data[frame.StackIndex - 2] = (Boolean?)(l ^ r); frame.StackIndex--; return 1; } @@ -127,6 +198,22 @@ namespace Microsoft.Scripting.Interpreter { } } + public static Instruction CreateLifted(Type type) { + Debug.Assert(!type.IsEnum()); + switch (type.GetTypeCode()) { + case TypeCode.Int16: return _Int16Lifted ?? (_Int16Lifted = new XorInt16Lifted()); + case TypeCode.Int32: return _Int32Lifted ?? (_Int32Lifted = new XorInt32Lifted()); + case TypeCode.Int64: return _Int64Lifted ?? (_Int64Lifted = new XorInt64Lifted()); + case TypeCode.UInt16: return _UInt16Lifted ?? (_UInt16Lifted = new XorUInt16Lifted()); + case TypeCode.UInt32: return _UInt32Lifted ?? (_UInt32Lifted = new XorUInt32Lifted()); + case TypeCode.UInt64: return _UInt64Lifted ?? (_UInt64Lifted = new XorUInt64Lifted()); + case TypeCode.Boolean: return _BooleanLifted ?? (_BooleanLifted = new XorBooleanLifted()); + + default: + throw Assert.Unreachable; + } + } + public override string ToString() { return "Xor()"; } diff --git a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs index fa98324b654..32a1bd4e91e 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightCompiler.cs @@ -566,29 +566,29 @@ namespace Microsoft.Scripting.Interpreter { return; case ExpressionType.Equal: - CompileEqual(node.Left, node.Right); + CompileEqual(node.Left, node.Right, node.IsLiftedToNull); return; case ExpressionType.NotEqual: - CompileNotEqual(node.Left, node.Right); + CompileNotEqual(node.Left, node.Right, node.IsLiftedToNull); return; case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: - CompileComparison(node.NodeType, node.Left, node.Right); + CompileComparison(node.NodeType, node.Left, node.Right, node.IsLiftedToNull); return; case ExpressionType.LeftShift: case ExpressionType.RightShift: - CompileShift(node.NodeType, node.Left, node.Right); + CompileShift(node.NodeType, node.Left, node.Right, node.IsLifted); return; case ExpressionType.And: case ExpressionType.Or: case ExpressionType.ExclusiveOr: - CompileLogical(node.NodeType, node.Left, node.Right); + CompileLogical(node.NodeType, node.Left, node.Right, node.IsLifted); return; default: @@ -597,34 +597,31 @@ namespace Microsoft.Scripting.Interpreter { } } - private void CompileEqual(Expression left, Expression right) { + private void CompileEqual(Expression left, Expression right, bool liftedResult) { Debug.Assert(left.Type == right.Type || !left.Type.IsValueType() && !right.Type.IsValueType()); Compile(left); Compile(right); - _instructions.EmitEqual(left.Type); + _instructions.EmitEqual(left.Type, liftedResult); } - private void CompileNotEqual(Expression left, Expression right) { + private void CompileNotEqual(Expression left, Expression right, bool liftedResult) { Debug.Assert(left.Type == right.Type || !left.Type.IsValueType() && !right.Type.IsValueType()); Compile(left); Compile(right); - _instructions.EmitNotEqual(left.Type); + _instructions.EmitNotEqual(left.Type, liftedResult); } - private void CompileComparison(ExpressionType nodeType, Expression left, Expression right) { + private void CompileComparison(ExpressionType nodeType, Expression left, Expression right, bool liftedResult) { Debug.Assert(left.Type == right.Type && TypeUtils.IsNumeric(left.Type)); - // TODO: - // if (TypeUtils.IsNullableType(left.Type) && liftToNull) ... - Compile(left); Compile(right); switch (nodeType) { - case ExpressionType.LessThan: _instructions.EmitLessThan(left.Type); break; - case ExpressionType.LessThanOrEqual: _instructions.EmitLessThanOrEqual(left.Type); break; - case ExpressionType.GreaterThan: _instructions.EmitGreaterThan(left.Type); break; - case ExpressionType.GreaterThanOrEqual: _instructions.EmitGreaterThanOrEqual(left.Type); break; + case ExpressionType.LessThan: _instructions.EmitLessThan(left.Type, liftedResult); break; + case ExpressionType.LessThanOrEqual: _instructions.EmitLessThanOrEqual(left.Type, liftedResult); break; + case ExpressionType.GreaterThan: _instructions.EmitGreaterThan(left.Type, liftedResult); break; + case ExpressionType.GreaterThanOrEqual: _instructions.EmitGreaterThanOrEqual(left.Type, liftedResult); break; default: throw Assert.Unreachable; } } @@ -646,25 +643,25 @@ namespace Microsoft.Scripting.Interpreter { } } - private void CompileShift(ExpressionType nodeType, Expression left, Expression right) { - Debug.Assert(right.Type == typeof (int)); + private void CompileShift(ExpressionType nodeType, Expression left, Expression right, bool lifted) { + Debug.Assert(right.Type == typeof (int) || right.Type == typeof (int?)); Compile(left); Compile(right); switch (nodeType) { - case ExpressionType.LeftShift: _instructions.EmitShl(left.Type); break; - case ExpressionType.RightShift: _instructions.EmitShr(left.Type); break; + case ExpressionType.LeftShift: _instructions.EmitShl(TypeUtils.GetNonNullableType (left.Type), lifted); break; + case ExpressionType.RightShift: _instructions.EmitShr(TypeUtils.GetNonNullableType (left.Type), lifted); break; default: throw Assert.Unreachable; } } - private void CompileLogical(ExpressionType nodeType, Expression left, Expression right) { - Debug.Assert(left.Type == right.Type && TypeUtils.IsIntegerOrBool(left.Type)); + private void CompileLogical(ExpressionType nodeType, Expression left, Expression right, bool lifted) { + Debug.Assert(left.Type == right.Type); // && TypeUtils.IsIntegerOrBool(left.Type)); Compile(left); Compile(right); switch (nodeType) { - case ExpressionType.And: _instructions.EmitAnd(left.Type); break; - case ExpressionType.Or: _instructions.EmitOr(left.Type); break; - case ExpressionType.ExclusiveOr: _instructions.EmitExclusiveOr(left.Type); break; + case ExpressionType.And: _instructions.EmitAnd(TypeUtils.GetNonNullableType (left.Type), lifted); break; + case ExpressionType.Or: _instructions.EmitOr(TypeUtils.GetNonNullableType (left.Type), lifted); break; + case ExpressionType.ExclusiveOr: _instructions.EmitExclusiveOr(TypeUtils.GetNonNullableType (left.Type), lifted); break; default: throw Assert.Unreachable; } } @@ -674,6 +671,9 @@ namespace Microsoft.Scripting.Interpreter { if (node.Method != null) { Compile(node.Operand); + if (node.IsLifted) + throw new NotImplementedException (); + // We should be able to ignore Int32ToObject if (node.Method != Runtime.ScriptingRuntimeHelpers.Int32ToObjectMethod) { EmitCall(node.Method); @@ -693,6 +693,32 @@ namespace Microsoft.Scripting.Interpreter { return; } + if (TypeUtils.IsNullableType (typeTo)) { + typeFrom = TypeUtils.GetNonNullableType (typeFrom); + typeTo = TypeUtils.GetNonNullableType (typeTo); + + var nullValue = _instructions.MakeLabel(); + var end = _instructions.MakeLabel(); + + _instructions.EmitDup (); + _instructions.EmitBranchNull(nullValue); + CompileConvertToType (typeFrom, typeTo, isChecked); + _instructions.EmitWrap (typeTo); + _instructions.EmitBranch (end); + _instructions.MarkLabel(nullValue); + _instructions.EmitDup (); // Keep null on the stack + _instructions.MarkLabel(end); + return; + } + + if (TypeUtils.IsNullableType (typeFrom)) { + if (typeTo.IsClass) + return; + + // TODO: should throw same exception as (int)(int?)null + throw new NotImplementedException (); + } + TypeCode from = typeFrom.GetTypeCode(); TypeCode to = typeTo.GetTypeCode(); if (TypeUtils.IsNumeric(from) && TypeUtils.IsNumeric(to)) { @@ -709,14 +735,14 @@ namespace Microsoft.Scripting.Interpreter { return; } - private void CompileNegateExpression(UnaryExpression node, bool @checked) { + private void CompileNegateExpression(UnaryExpression node, bool @checked, bool lifted) { Compile(node.Operand); - _instructions.EmitNegate(node.Type, @checked); + _instructions.EmitNegate(TypeUtils.GetNonNullableType (node.Type), @checked, lifted); } - private void CompileNotExpression(UnaryExpression node) { + private void CompileNotExpression(UnaryExpression node, bool lifted) { Compile(node.Operand); - _instructions.EmitNot(node.Type); + _instructions.EmitNot(TypeUtils.GetNonNullableType (node.Type), lifted); } private void CompileUnaryExpression(Expression expr) { @@ -732,13 +758,13 @@ namespace Microsoft.Scripting.Interpreter { _instructions.EmitGetArrayLength (node.Type); return; case ExpressionType.Negate: - CompileNegateExpression(node, false); + CompileNegateExpression(node, false, node.IsLifted); return; case ExpressionType.NegateChecked: - CompileNegateExpression(node, true); + CompileNegateExpression(node, true, node.IsLifted); return; case ExpressionType.Not: - CompileNotExpression(node); + CompileNotExpression(node, node.IsLifted); return; case ExpressionType.UnaryPlus: // unary plus is a nop: @@ -1535,6 +1561,10 @@ namespace Microsoft.Scripting.Interpreter { var node = (TypeBinaryExpression)expr; Compile(node.Expression); + if (node.Expression.Type == typeof (void)) { + _instructions.Emit (InstructionFactory<bool>.Factory.DefaultValue ()); + return; + } // use TypeEqual for sealed types: if (node.TypeOperand.IsSealed()) { |