diff options
author | Andy Ayers <andya@microsoft.com> | 2020-01-14 10:36:18 -0800 |
---|---|---|
committer | Anirudh Agnihotry <anirudhagnihotry098@gmail.com> | 2020-01-14 10:36:18 -0800 |
commit | 2f99ca8652bd31755aac431dc1bff8a4dda888eb (patch) | |
tree | db156299e8836296244968c2b06f3443c030d5cf /src/jit | |
parent | 1e0eabe8ed5ca2d5fc8fef89a60e59f5a641bb6f (diff) | |
download | coreclr-2f99ca8652bd31755aac431dc1bff8a4dda888eb.tar.gz coreclr-2f99ca8652bd31755aac431dc1bff8a4dda888eb.tar.bz2 coreclr-2f99ca8652bd31755aac431dc1bff8a4dda888eb.zip |
[release/3.1] Port fix for JIT silent bad code (#27972)
* [release/3.1] Port fix for JIT silent bad code
Release/3.1 port of https://github.com/dotnet/runtime/pull/797.
Fixes https://github.com/dotnet/runtime/issues/764
The jit might incorrectly order a read from a struct field with an operation
that modifies the field, so that the read returns the wrong value.
Silent bad code; program behaves incorrectly.
Yes, introduced in the 3.0 cycle.
Verified the user's test case now passes; no diffs seen in any existing framework
or test code.
**Low**: the jit is now spilling the eval stack entries to temps in cases where it
did not before; this should be conservatively safe.
cc: @brucefo
____
If we're appending an assignment whose LHS is is a location within a local
struct, we need to spill all references to that struct from the eval stack.
Update the existing logic for this to handle the case where the LHS is a field
of a local struct, and the field is updated by unusual means (here, `initobj`).
Fixes dotnet/runtime#764.
* Fix test
Diffstat (limited to 'src/jit')
-rw-r--r-- | src/jit/importer.cpp | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index bbb0d14e97..50ddc58d89 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -10837,11 +10837,22 @@ void Compiler::impImportBlockCode(BasicBlock* block) } else if (lhs->OperIsBlk()) { - // Check for ADDR(LCL_VAR), or ADD(ADDR(LCL_VAR),CNS_INT)) - // (the latter may appear explicitly in the IL). - // Local field stores will cause the stack to be spilled when - // they are encountered. - lclVar = lhs->AsBlk()->Addr()->IsLocalAddrExpr(); + // Check if LHS address is within some struct local, to catch + // cases where we're updating the struct by something other than a stfld + GenTree* addr = lhs->AsBlk()->Addr(); + + // Catches ADDR(LCL_VAR), or ADD(ADDR(LCL_VAR),CNS_INT)) + lclVar = addr->IsLocalAddrExpr(); + + // Catches ADDR(FIELD(... ADDR(LCL_VAR))) + if (lclVar == nullptr) + { + GenTree* lclTree = nullptr; + if (impIsAddressInLocal(addr, &lclTree)) + { + lclVar = lclTree->AsLclVarCommon(); + } + } } if (lclVar != nullptr) { |