Fix issue #11446. (#11455)
authorPat Gavlin <pgavlin@gmail.com>
Tue, 9 May 2017 18:10:00 +0000 (11:10 -0700)
committerGitHub <noreply@github.com>
Tue, 9 May 2017 18:10:00 +0000 (11:10 -0700)
This issue was a GC hole that was caused by bad IR produced by
recursivelty promoting a struct with the following form:

```
struct S
{
    struct T
    {
        object o;
    };

    T t;
}
```

In this case, the recursive promotion logic created a single lclVar to
represent `S.t` and retyped it using the type of `T.o`, but did not
rewrite IR that treated the single lclVar as a struct (e.g. instances of
`lclFld/st.lclFld Vx` where `Vx` referred to the lclVar that represented
`S.t` were not rewritten an `lclVar/st.lclVar Vx`). This IR in
turn confused the incremental liveness used during code generation,
which caused the stack slot holding `o`'s value to die too early.

This change fixes codegen's incremental liveness to handle this case.

src/jit/codegenlinear.cpp
src/jit/codegenxarch.cpp

index b0fb36f..afc7db3 100644 (file)
@@ -1228,7 +1228,7 @@ void CodeGen::genConsumeRegs(GenTree* tree)
             genConsumeAddress(tree->AsIndir()->Addr());
         }
 #ifdef _TARGET_XARCH_
-        else if (tree->OperGet() == GT_LCL_VAR)
+        else if (tree->OperIsLocalRead())
         {
             // A contained lcl var must be living on stack and marked as reg optional, or not be a
             // register candidate.
index d693ff9..42f041d 100644 (file)
@@ -1558,6 +1558,8 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
             GenTreePtr op1 = treeNode->gtGetOp1();
             genConsumeRegs(op1);
             emit->emitInsBinary(ins_Store(targetType), emitTypeSize(treeNode), treeNode, op1);
+
+            genUpdateLife(treeNode);
         }
         break;