Skip to content

Commit

Permalink
Merge pull request dotnet/coreclr#27114 from erozenfeld/Fix27027
Browse files Browse the repository at this point in the history
Jit: Fix SetIndirExceptionFlags.

Commit migrated from dotnet/coreclr@58b016c
  • Loading branch information
erozenfeld authored Oct 11, 2019
2 parents 66fc6f2 + 45ca544 commit b0968e2
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 18 deletions.
34 changes: 33 additions & 1 deletion src/coreclr/src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7952,7 +7952,7 @@ void Compiler::gtUpdateNodeOperSideEffects(GenTree* tree)
tree->gtFlags &= ~GTF_EXCEPT;
if (tree->OperIsIndirOrArrLength())
{
tree->gtFlags |= GTF_IND_NONFAULTING;
tree->SetIndirExceptionFlags(this);
}
}

Expand Down Expand Up @@ -9270,6 +9270,38 @@ bool GenTree::Precedes(GenTree* other)
return false;
}

//------------------------------------------------------------------------------
// SetIndirExceptionFlags : Set GTF_EXCEPT and GTF_IND_NONFAULTING flags as appropriate
// on an indirection or an array length node.
//
// Arguments:
// comp - compiler instance
//

void GenTree::SetIndirExceptionFlags(Compiler* comp)
{
GenTree* addr = nullptr;
if (OperIsIndir())
{
addr = AsIndir()->Addr();
}
else
{
assert(gtOper == GT_ARR_LENGTH);
addr = AsArrLen()->ArrRef();
}

if (OperMayThrow(comp) || ((addr->gtFlags & GTF_EXCEPT) != 0))
{
gtFlags |= GTF_EXCEPT;
}
else
{
gtFlags &= ~GTF_EXCEPT;
gtFlags |= GTF_IND_NONFAULTING;
}
}

#ifdef DEBUG

/* static */ int GenTree::gtDispFlags(unsigned flags, unsigned debugFlags)
Expand Down
6 changes: 1 addition & 5 deletions src/coreclr/src/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -2099,11 +2099,7 @@ struct GenTree
gtFlags &= ~GTF_REUSE_REG_VAL;
}

void SetIndirExceptionFlags(Compiler* comp)
{
assert(OperIsIndirOrArrLength());
gtFlags |= OperMayThrow(comp) ? GTF_EXCEPT : GTF_IND_NONFAULTING;
}
void SetIndirExceptionFlags(Compiler* comp);

#if MEASURE_NODE_SIZE
static void DumpNodeSizes(FILE* fp);
Expand Down
24 changes: 12 additions & 12 deletions src/coreclr/src/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6193,7 +6193,6 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac)
tree->SetOper(GT_IND);
tree->gtOp.gtOp1 = addr;

tree->gtFlags &= (~GTF_EXCEPT | addr->gtFlags);
tree->SetIndirExceptionFlags(this);

if (addExplicitNullCheck)
Expand Down Expand Up @@ -8864,7 +8863,6 @@ GenTree* Compiler::fgMorphOneAsgBlockOp(GenTree* tree)
tree->gtFlags |= GTF_GLOB_REF;
}

dest->gtFlags &= (~GTF_EXCEPT | dest->AsIndir()->Addr()->gtFlags);
dest->SetIndirExceptionFlags(this);
tree->gtFlags |= (dest->gtFlags & GTF_EXCEPT);
}
Expand Down Expand Up @@ -8911,7 +8909,6 @@ GenTree* Compiler::fgMorphOneAsgBlockOp(GenTree* tree)
src->gtFlags |= (GTF_GLOB_REF | GTF_IND_TGTANYWHERE);
}

src->gtFlags &= (~GTF_EXCEPT | src->AsIndir()->Addr()->gtFlags);
src->SetIndirExceptionFlags(this);
}
}
Expand Down Expand Up @@ -11761,21 +11758,24 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)

DONE_MORPHING_CHILDREN:

if (tree->OperMayThrow(this))
if (tree->OperIsIndirOrArrLength())
{
// Mark the tree node as potentially throwing an exception
tree->gtFlags |= GTF_EXCEPT;
tree->SetIndirExceptionFlags(this);
}
else
{
if (tree->OperIsIndirOrArrLength())
if (tree->OperMayThrow(this))
{
tree->gtFlags |= GTF_IND_NONFAULTING;
// Mark the tree node as potentially throwing an exception
tree->gtFlags |= GTF_EXCEPT;
}
if (((op1 == nullptr) || ((op1->gtFlags & GTF_EXCEPT) == 0)) &&
((op2 == nullptr) || ((op2->gtFlags & GTF_EXCEPT) == 0)))
else
{
tree->gtFlags &= ~GTF_EXCEPT;
if (((op1 == nullptr) || ((op1->gtFlags & GTF_EXCEPT) == 0)) &&
((op2 == nullptr) || ((op2->gtFlags & GTF_EXCEPT) == 0)))
{
tree->gtFlags &= ~GTF_EXCEPT;
}
}
}

Expand Down Expand Up @@ -14662,7 +14662,7 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac)
tree->gtDynBlk.Addr() = fgMorphTree(tree->gtDynBlk.Addr());
tree->gtDynBlk.gtDynamicSize = fgMorphTree(tree->gtDynBlk.gtDynamicSize);

tree->gtFlags &= (~GTF_EXCEPT & ~GTF_CALL);
tree->gtFlags &= ~GTF_CALL;
tree->SetIndirExceptionFlags(this);

if (tree->OperGet() == GT_STORE_DYN_BLK)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Runtime.CompilerServices;

public struct S
{
public int i;
public int j;
}

public class Test
{
public S s;

public static int Main()
{
// Test that the correct exception is thrown from Run.
// The bug was that the exceptions were reordered and DivideByZeroException
// was thrown instead of NullReferenceException.
try {
Run(null, 0);
}
catch (System.NullReferenceException)
{
return 100;
}

return -1;
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static int Run(Test test, int j)
{
int k = test.s.i + 1/j;
return k;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<CLRTestPriority>1</CLRTestPriority>
</PropertyGroup>
<PropertyGroup>
<DebugType />
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>

0 comments on commit b0968e2

Please sign in to comment.