Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable peverify-compat mode for langver < 7.2 #22772

Merged
merged 3 commits into from
Nov 3, 2017
Merged

Conversation

VSadov
Copy link
Member

@VSadov VSadov commented Oct 19, 2017

Ensures that the behavior of the compiler with respect to verification compat is:

  • Langver < 7.2 enables compat mode automatically
  • Fature flag ”peverify-compat” enables compat mode
  • In compat mode - no unverifiable optimizations in code that used to verify in the past.
  • In compat mode - new intrinsically unverifiable features/patterns work correctly, even if unverifiable code needs to be emitted (correctness wins in this case).

Customer scenario

This change primarily impacts users that use CAS attributes such as [SecurityTransparent] in the code. The situation is not common, but the experience could be bad enough to be an adoption blocker.

  • user upgrades to the new compiler and upon recompile app crashes with security exceptions even though nothing whatsoever changed.

Note -
User may keep langver < 7.2 as it was, in such case indeed nothing changed, or
user may switch to langver == 7.2 or latest, but not use new features or use only a subset such
as relaxed rules for named arguments.
In either case user may need to have a way to compile code into something that does not crash.

Bugs this fixes:

#22707

Workarounds, if any

User may use feature flag "peverify-compat", but if he uses new features, that may result in code that is both not verifiable and not correct.

Ideally, as long as langver is the same as before, no changes should be required.
Also presence of the flag should not result in bad codegen for new features.

Basically without this fix user will 1) have to set the flag and then 2) end up in a strict either/or situation for the new features.

Even if not common [SecurityTransparent] code still exists, for whatever reasons. We have already had 3 separate reports about breaks as described above.
There is a concern that experience as it is now could become an adoption blocker for a subset of customers, expecialy with large legacy code bases.

Risk

Risk is low since this is basically enabling a compat mode automatically in situations when user already can enable it.
The change also makes the compat mode to not interfere with new code. That is specifically to reduce the risk of using the compat mode.

Performance impact

Low, since most changes are just around choosing different IL emit strategies based on a flag or a langver value.
There are no new allocations or complicated logic.

Is this a regression from a previous update?

No.

Root cause analysis:

Early feedback from previews and internal use, such as using new compiler in CoreFx, reveals that while use of features like [SecurityTransparent] is uncommon, it does exist and user experience is not as good as we would like.
In the light of this new data the risk of leaving the situation as-is now seems higher.

How was the bug found?

Build beaks in System.Immutable.Collections in CoreFx repo
Customer reports.

Test documentation updated?
N/A
new tests added.

VSO bug:
https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?id=514815&_a=edit

@VSadov VSadov added the PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. label Oct 19, 2017
@VSadov VSadov changed the title Emit correct code when demands of new features interfere with peverify-compat. Enable peverify-compat mode for langver < 7.2 Oct 19, 2017
@VSadov VSadov added Area-Compilers and removed PR For Personal Review Only The PR doesn’t require anyone other than the developer to review it. labels Oct 20, 2017
@VSadov VSadov added this to the 15.5 milestone Oct 20, 2017
@VSadov VSadov force-pushed the compatFixes branch 2 times, most recently from 2cc7cd1 to d089bf9 Compare October 20, 2017 01:17
@MeiChin-Tsai
Copy link

Please get code reviewed. Approved for the fix as long as code reviewers have no objection.

Copy link
Member

@agocke agocke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any ref readonly local tests?

@@ -139,7 +139,7 @@ private bool IsDebugPlus()

private bool EnablePEVerifyCompat()
Copy link
Member

@agocke agocke Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads like a mutating method, but is actually flag-returning. How about IsPEVerifyCompatEnabled? #WontFix

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Someone suggested this name in past CR. I would be ok with renaming this and perhaps other helpers (like "HasValue") to be more matching with their purpose, but not in this change. We can rename/refactor later.


In reply to: 146959260 [](ancestors = 146959260)

@@ -339,7 +345,7 @@ private LocalSymbol DigForValueLocal(BoundSequence topSequence, BoundExpression
/// Checks if expression directly or indirectly represents a value with its own home. In
/// such cases it is possible to get a reference without loading into a temporary.
/// </summary>
private bool HasHome(BoundExpression expression, bool needWriteable)
private bool HasHome(BoundExpression expression, AddressKind addressKind)
Copy link
Member

@agocke agocke Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressKind here refers to the destination, so maybe call it destinationAddressKind or requiredAddressKind? #WontFix

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to rename this "HasHome" to something like "CanGetDirectReference" or similar (in a separate clean-up change). I started doing that, but reverted since that does not need to be in 15.5 and just makes the PR larger than it needs to be.
Then "requiredAddressKind" would be Ok.


In reply to: 146960213 [](ancestors = 146960213)

@@ -437,7 +444,14 @@ private bool HasHome(BoundFieldAccess fieldAccess, bool needWriteable)
return false;
}

if (!needWriteable && !EnablePEVerifyCompat())
// when reference is strictly required, consider fields as addressable
Copy link
Member

@agocke agocke Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this comment says what you mean. Even if we copy into a temp, you're going to get an address back. Really, this is a statement about not being allowed to copy. #Resolved

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. The idea is that direct reference is strongly desired.


In reply to: 146961206 [](ancestors = 146961206)

//NOTE: we are not propagating AddressKind.Constrained here.
// the reason is that while Constrained permits calls, it does not permit
// taking field addresses, so we have to turn Constrained into writeable.
var tempOpt = EmitReceiverRef(fieldAccess.ReceiverOpt, addressKind == AddressKind.Constrained? AddressKind.Writeable: addressKind);
Copy link
Member

@agocke agocke Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange formatting around the ?: operator. #Resolved

}
else
{
// vararg case
Copy link
Member

@agocke agocke Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider asserting that the last parameter is a vararg here. #Resolved

LocalDefinition temp = EmitAddress(assignmentOperator.Right, AddressKind.ReadOnly);
// NOTE: passing "ReadOnlyStrict" here.
// we should not get an address of a copy if at all possible
LocalDefinition temp = EmitAddress(assignmentOperator.Right, local.RefKind == RefKind.RefReadOnly ? AddressKind.ReadOnlyStrict: AddressKind.Writeable);
Copy link
Member

@agocke agocke Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a space before the : #Resolved

@@ -724,7 +724,9 @@ private void EmitReturnStatement(BoundReturnStatement boundReturnStatement)
}
else
{
this.EmitAddress(expressionOpt, this._method.RefKind == RefKind.RefReadOnly? AddressKind.ReadOnly: AddressKind.Writeable);
// NOTE: passing "ReadOnlyStrict" here.
// we should not get an address of a copy if at all possible
Copy link
Member

@agocke agocke Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make a stronger statement: we cannot ever return the address of a copy. #Resolved

IL_000a: ldind.i4
IL_000b: call ""void System.Console.WriteLine(int)""
IL_0010: ret
}");
Copy link
Member

@cston cston Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main is identical in both cases. Should there be a difference in M(in int)? (We're not checking the IL for that method.) #ByDesign

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is the point of the test - main passes a readonly field as an "in" parameter. The only way to do it correctly is unverifiable, therefore the presence of the compat flag should not change IL of Main. - if we see different IL, we would have a bug (that was a case before this fix).

M is not very interesting here. Unlike with fields, verifier does not care if parameter is "in".


In reply to: 146964668 [](ancestors = 146964668)

CompileAndVerify(comp, verify: false, expectedOutput: @"47");

comp = CreateCompilationWithMscorlib46(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.UnsafeReleaseExe, parseOptions: TestOptions.Regular.WithPEVerifyCompatFeature());
CompileAndVerify(comp, verify: false, expectedOutput: @"47");
Copy link
Member

@cston cston Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider verifying IL for the affected methods. #Resolved


";

var comp = CreateCompilationWithMscorlib46(text, new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.UnsafeReleaseExe);
Copy link
Member

@cston cston Oct 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the references necessary? #WontFix

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just copied from other test. They will not make it a better or worse, so I will let them be.


In reply to: 146965555 [](ancestors = 146965555)

Copy link
Member

@agocke agocke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the ref readonly local tests now. LGTM

@jcouv
Copy link
Member

jcouv commented Oct 30, 2017

What's the status on this PR? Are we waiting for shiproom approval?

@jcouv
Copy link
Member

jcouv commented Nov 3, 2017

@jcouv
Copy link
Member

jcouv commented Nov 3, 2017

test perf_correctness_prtest please

@natidea
Copy link
Contributor

natidea commented Nov 3, 2017

@jcouv jcouv merged commit ab63bff into dotnet:master Nov 3, 2017
@VSadov
Copy link
Member Author

VSadov commented Nov 3, 2017

Thanks!!!

@VSadov VSadov deleted the compatFixes branch November 3, 2017 19:20
333fred added a commit to 333fred/roslyn that referenced this pull request Nov 8, 2017
* dotnet/master: (36 commits)
  Remove usage of IOperation feature flag in newly added unit tests
  More fixes for IOperation tree. (dotnet#23028)
  Address PR feedback and remove unused resource and comment out unused error code
  Remove IOperation feature flag and internal registration APIs for operations
  Add unit test for VB
  Address review feedback and add more unit tests
  Fix unit tests
  Fix build errors from merge resolution
  Revert unintentional newline deletion
  Address recent feedback and do not generate an IParenthesizedOperation for C#. This change is now just a test-only change that verifies the current behavior.
  Address PR feedback and use singleton for null instance
  Address PR feedback
  Address PR feedback
  Do not invoke GetStandaloneNode helper in GetOperationWorker
  Fix InvalidCastException in CSharpOperationFactory for invalid nested member initializer (dotnet#22983)
  Use ICollection<string>.Contains to avoid Enumerator allocation
  Add IsRef property to IConditionalOperation and ISimpleAssignmentOperation, add RefKind property to ILocalSymbol. (dotnet#22933)
  Enable peverify-compat mode for langver < 7.2 (dotnet#22772)
  Properly detect root of a tree in Operation.SearchParentOperation (dotnet#22974)
  Fix IArgument and IArrayInitializer to have null types
  ...
333fred added a commit to 333fred/roslyn that referenced this pull request Nov 9, 2017
* dotnet/master: (28 commits)
  Fix the operation verifier code now that getoperationinternal no longer exists.
  Remove usage of IOperation feature flag in newly added unit tests
  More fixes for IOperation tree. (dotnet#23028)
  Address PR feedback and remove unused resource and comment out unused error code
  Remove IOperation feature flag and internal registration APIs for operations
  Add unit test for VB
  Address review feedback and add more unit tests
  Fix unit tests
  Fix build errors from merge resolution
  Revert unintentional newline deletion
  Address recent feedback and do not generate an IParenthesizedOperation for C#. This change is now just a test-only change that verifies the current behavior.
  Address PR feedback and use singleton for null instance
  Address PR feedback
  Address PR feedback
  Do not invoke GetStandaloneNode helper in GetOperationWorker
  Fix InvalidCastException in CSharpOperationFactory for invalid nested member initializer (dotnet#22983)
  Use ICollection<string>.Contains to avoid Enumerator allocation
  Add IsRef property to IConditionalOperation and ISimpleAssignmentOperation, add RefKind property to ILocalSymbol. (dotnet#22933)
  Enable peverify-compat mode for langver < 7.2 (dotnet#22772)
  Fix IArgument and IArrayInitializer to have null types
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants