Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/FastExpressionCompiler/FastExpressionCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,7 @@ public void PopBlock()
for (var i = 0; i < varCount; ++i)
{
ref var varBlocks = ref _varInBlock.Map.GetSurePresentEntryRef(i);
if (varBlocks.Value.Count == _blockCount)
if (varBlocks.Value.Count != 0 && (varBlocks.Value.GetLastSurePresentRef() >>> 16) == _blockCount - 1)
varBlocks.Value.RemoveLastSurePresent();
}
--_blockCount;
Expand Down
2 changes: 2 additions & 0 deletions test/FastExpressionCompiler.TestsRunner.Net472/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ static void RunLightExpressionTests(object state)
var justLightTestsStopwatch = Stopwatch.StartNew();

var t = (LightExpression.TestRun)state;
t.Run(new LightExpression.UnitTests.BlockVariableBindingRegressionTests());
t.Run(new LightExpression.UnitTests.NestedStructFieldAddressRegressionTests());
t.Run(new LightExpression.IssueTests.Issue183_NullableDecimal());
t.Run(new LightExpression.IssueTests.Issue398_Optimize_Switch_with_OpCodes_Switch());
Expand All @@ -60,6 +61,7 @@ static void RunLightExpressionTests(object state)
var fecTestsStopwatch = Stopwatch.StartNew();

var fecTests = new TestRun();
fecTests.Run(new BlockVariableBindingRegressionTests());
fecTests.Run(new NestedStructFieldAddressRegressionTests());
fecTests.Run(new Issue183_NullableDecimal());
fecTests.Run(new Issue468_Optimize_the_delegate_access_to_the_Closure_object_for_the_modern_NET());
Expand Down
2 changes: 2 additions & 0 deletions test/FastExpressionCompiler.TestsRunner/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public static void Main(string[] args)
var ltTask = Task.Run(() =>
{
var ltStopwatch = Stopwatch.StartNew();
lt.Run(new LightExpression.UnitTests.BlockVariableBindingRegressionTests());
#if NET8_0_OR_GREATER
lt.Run(new LightExpression.UnitTests.NestedStructFieldAddressRegressionTests());
lt.Run(new LightExpression.IssueTests.Issue490_Regression_in_compiling_lambdas_with_ref_struct_parameters());
Expand All @@ -86,6 +87,7 @@ public static void Main(string[] args)
});

var stStopwatch = Stopwatch.StartNew();
st.Run(new BlockVariableBindingRegressionTests());
st.Run(new NestedStructFieldAddressRegressionTests());
st.Run(new Issue499_InvalidProgramException_for_Sorting_and_comparison_function());
st.Run(new Issue561_NonBooleanEqualityOperator());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using S = System.Linq.Expressions.Expression;
#if LIGHT_EXPRESSION
namespace FastExpressionCompiler.LightExpression.UnitTests;
#else
namespace FastExpressionCompiler.UnitTests;
#endif

public struct BlockVariableBindingRegressionTests : ITestX
{
private static readonly CompilerFlags[] Flags =
{
CompilerFlags.Default, CompilerFlags.NoInvocationLambdaInlining,
CompilerFlags.EnableDelegateDebugInfo | CompilerFlags.ThrowOnNotSupportedExpression
};

public void Run(TestRun t)
{
Leaving_nested_binding_restores_outer_value(t);
Sibling_redeclarations_restore_outer_value(t);
Direct_nested_and_distinct_bindings_keep_their_values(t);
}

public void Leaving_nested_binding_restores_outer_value(TestContext t)
{
var value = S.Variable(typeof(int), "value");
var middle = S.Variable(typeof(int), "middle");
var tree = S.Lambda<Func<int>>(S.Block(new[] { value },
S.Assign(value, S.Constant(1)),
S.Block(new[] { middle }, S.Assign(middle, S.Constant(0)),
S.Block(new[] { value }, S.Assign(value, S.Constant(2))), value)));
var expected = tree.Compile()();
t.AreEqual(1, expected);
foreach (var flags in Flags)
{
var fast = tree.FromSysExpression().CompileFast(true, flags);
if (t.IsNotNull(fast)) t.AreEqual(expected, fast());
}
}

public void Sibling_redeclarations_restore_outer_value(TestContext t)
{
var value = S.Variable(typeof(int), "value");
var sum = S.Variable(typeof(int), "sum");
var statements = new List<System.Linq.Expressions.Expression>
{
S.Assign(value, S.Constant(1)), S.Assign(sum, S.Constant(0))
};
for (var i = 0; i < 3; ++i)
{
var middle = S.Variable(typeof(int), "middle");
statements.Add(S.Block(new[] { middle }, S.Assign(middle, S.Constant(0)),
S.Block(new[] { value }, S.Assign(value, S.Constant(i + 10))), S.AddAssign(sum, value)));
}
statements.Add(sum);
var tree = S.Lambda<Func<int>>(S.Block(new[] { value, sum }, statements));
var expected = tree.Compile()();
t.AreEqual(3, expected);
foreach (var flags in Flags)
{
var fast = tree.FromSysExpression().CompileFast(true, flags);
if (t.IsNotNull(fast)) t.AreEqual(expected, fast());
}
}

public void Direct_nested_and_distinct_bindings_keep_their_values(TestContext t)
{
var value = S.Variable(typeof(int), "value");
var other = S.Variable(typeof(int), "other");
var tree = S.Lambda<Func<int>>(S.Block(new[] { value }, S.Assign(value, S.Constant(1)),
S.Block(new[] { value }, S.Assign(value, S.Constant(2))),
S.Block(new[] { other }, S.Assign(other, S.Constant(3))), value));
var expected = tree.Compile()();
t.AreEqual(1, expected);
foreach (var flags in Flags)
{
var fast = tree.FromSysExpression().CompileFast(true, flags);
if (t.IsNotNull(fast)) t.AreEqual(expected, fast());
}
}
}
Loading