Fix to VectorCopyTo test that are failing with NullReferencException on an AVX2 machine.
authorVenkata Sivaramakrishna Ramadugu <sivarv@microsoft.com>
Tue, 22 Sep 2015 18:28:24 +0000 (11:28 -0700)
committerVenkata Sivaramakrishna Ramadugu <sivarv@microsoft.com>
Tue, 22 Sep 2015 18:28:24 +0000 (11:28 -0700)
Scenario: Vector2/3/4.CopyTo(array, idx) or Vector<T>.CopyTo(array, idx)

Expected: Here the second arg is out of range and an argument out of range exception is expected.

Observed: AV while generating helper call to throw range-check exception which gets propagated as NullReferenceException

Root cause:    If repro program being run is debug version (i.e. JIT is asked to execute minopts/debuggable code)

     genRangeCheck() ->genJumpToThrowHlpBlk(bndsChk->gtThrowKind) ->Compiler::acdHelper(codeKind)

     Since Compiler::acdHelper() doesn't have mapping for SCK_ARG_EXCPN and SCK_ARG_RNG_EXCPN it return zero as helper number.  On chk builds this further leads to asserts in VM when genEmitHelperCall()->compGetHelperFtn(helpernum) call is made.  On retail builds, it will lead to AV, which gets propagated as NullReferenceException.

     Why this doesn't repro on SSE2: SIMD intrinsics are disabled while generating minopts/debuggable code.
     Why does this repro on AVX2: Since VM used size for Vector<T> doesn't match IL definition of Vector<T>, JIT has no way but to support SIMD intrinsics even while generating minopts/debuggable code.

     On manual source examination found a couple of places where (in compiler.hpp) that are supposed to check for SCK_ARG_EXCPN and SCK_ARG_RNG_EXCPN and fixed those as well.

Fix dotnet/coreclr#3262

[tfs-changeset: 1527996]

Commit migrated from https://github.com/dotnet/coreclr/commit/a4882f5ed09736946ad7871f933c0e726b10b956

src/coreclr/src/jit/compiler.hpp
src/coreclr/src/jit/flowgraph.cpp

index 99459dd..1cdc939 100644 (file)
@@ -2797,6 +2797,8 @@ Compiler::fgWalkResult  Compiler::fgWalkTreePost(GenTreePtr    *pTree,
  * Has this block been added to throw an inlined exception
  * Returns true if the block was added to throw one of:
  *    range-check exception
+ *    argument exception (used by feature SIMD)
+ *    argument range-check exception (used by feature SIMD)
  *    divide by zero exception  (Not used on X86/X64)
  *    null reference exception (Not currently used)
  *    overflow exception
@@ -2834,7 +2836,12 @@ bool                Compiler::fgIsThrowHlpBlk(BasicBlock * block)
         {
             return add->acdKind == SCK_RNGCHK_FAIL ||
                    add->acdKind == SCK_DIV_BY_ZERO ||
-                   add->acdKind == SCK_OVERFLOW;
+                   add->acdKind == SCK_OVERFLOW
+#ifndef RYUJIT_CTPBUILD
+                   || add->acdKind == SCK_ARG_EXCPN
+                   || add->acdKind == SCK_ARG_RNG_EXCPN
+#endif //!RYUJIT_CTPBUILD
+                   ;
         }
     }
 
@@ -2855,6 +2862,17 @@ unsigned            Compiler::fgThrowHlpBlkStkLevel(BasicBlock *block)
     {
         if  (block == add->acdDstBlk)
         {
+            // Compute assert cond separately as assert macro cannot have conditional compilation directives.
+            bool cond = (add->acdKind == SCK_RNGCHK_FAIL ||
+                         add->acdKind == SCK_DIV_BY_ZERO ||
+                         add->acdKind == SCK_OVERFLOW
+#ifndef RYUJIT_CTPBUILD
+                         || add->acdKind == SCK_ARG_EXCPN
+                         || add->acdKind == SCK_ARG_RNG_EXCPN
+#endif //!RYUJIT_CTPBUILD
+                        );
+            assert(cond);
+
             assert(add->acdKind == SCK_RNGCHK_FAIL ||
                    add->acdKind == SCK_DIV_BY_ZERO ||
                    add->acdKind == SCK_OVERFLOW);
index 5e24ab9..84233d8 100644 (file)
@@ -17505,6 +17505,10 @@ unsigned            Compiler::acdHelper(SpecialCodeKind codeKind)
     switch (codeKind)
     {
     case SCK_RNGCHK_FAIL: return CORINFO_HELP_RNGCHKFAIL;
+#ifndef RYUJIT_CTPBUILD
+    case SCK_ARG_EXCPN: return CORINFO_HELP_THROW_ARGUMENTEXCEPTION;
+    case SCK_ARG_RNG_EXCPN: return CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION;
+#endif //!RYUJIT_CTPBUILD
     case SCK_DIV_BY_ZERO: return CORINFO_HELP_THROWDIVZERO;
     case SCK_ARITH_EXCPN: return CORINFO_HELP_OVERFLOW;
     default: assert(!"Bad codeKind"); return 0;
@@ -17618,8 +17622,10 @@ BasicBlock*         Compiler::fgAddCodeRef(BasicBlock*      srcBlk,
         case SCK_PAUSE_EXEC:    msg = " for PAUSE_EXEC";    break;
         case SCK_DIV_BY_ZERO:   msg = " for DIV_BY_ZERO";   break;
         case SCK_OVERFLOW:      msg = " for OVERFLOW";      break;
+#ifndef RYUJIT_CTPBUILD
         case SCK_ARG_EXCPN:     msg = " for ARG_EXCPN";     break;
         case SCK_ARG_RNG_EXCPN: msg = " for ARG_RNG_EXCPN"; break;
+#endif //!RYUJIT_CTPBUILD
         default:                msg = " for ??";            break;
         }