-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Concurrency issue with fixed fields #56581
Conversation
@@ -1417,17 +1417,6 @@ public NamedTypeSymbol SetFixedImplementationType(SourceMemberFieldSymbol field) | |||
} | |||
} | |||
|
|||
internal NamedTypeSymbol GetFixedImplementationType(FieldSymbol field) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 This code was not referenced.
58ac696
to
dab8420
Compare
.WithOverflowChecks(false) | ||
.WithModuleName(assemblyName); | ||
|
||
for (int j = 0; j < 10; j++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 I've tested with as many as 100 loops and max=100, but found this was a sufficient number to repro well
@@ -763,7 +763,7 @@ public ImmutableArray<ISymbolInternal> GetAllMembers() | |||
|
|||
if (NestedTypes != null) | |||
{ | |||
foreach (var type in NestedTypes) | |||
foreach (var type in NestedTypes.OrderBy(t => t.Name, StringComparer.Ordinal)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<forward declaringType=""{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointTypeName) }+<>c"" methodName=""<{ EscapeForXML(WellKnownMemberNames.TopLevelStatementsEntryPointMethodName) }>b__0_0"" /> | ||
<using> | ||
<namespace usingCount=""2"" /> | ||
</using> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change because namespace imports are now attached to a different method, because of re-ordered types? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this information about usings is order dependent. One method gets it and the following ones refer to the first method instead of repeating it.
Can we make this private and add a public In reply to: 930640897 Refers to: src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs:731 in a15e86b. [](commit_id = a15e86b, deletion_comment = False) |
byte[] result = null; | ||
|
||
var sourceBuilder = ArrayBuilder<string>.GetInstance(); | ||
int max = 20; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: const
#Resolved
Done review pass (commit 2) |
@333fred Please take another look. Thanks |
// Nested types may be queued from concurrent threads, but we need to emit them | ||
// in a deterministic order. | ||
internal IEnumerable<Cci.INestedTypeDefinition> DeterministicNestedTypes | ||
=> NestedTypes?.OrderBy(t => t.Name, StringComparer.Ordinal); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if you have multiple nested types with the same name, but different arity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not emit them in source-order (taking into account partials as well of course).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These nested types are synthesized. Not directly from source. I don't think we synthesize nested types with different arities. Could add this in 17.1 for extra safety (future-proofing)...
As for the order itself, I don't think there's a reason to prefer one specific order to another, as long as it's deterministic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we synthesize nested types with different arities
Can you add a contract call to that effect hten? if that assumption ever changes we want to update this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. I'll create a 17.1 PR to add assertion. Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, since this PR isn't merged yet, I'll add the assertion here. Still have time for tomorrow's deadline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (commit 3)
Debug.Assert(arities.All(a => a == arities.First())); | ||
} | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the assert be simplified (or perhaps documented)?
And should we simply assert that there are no duplicate names?
Perhaps:
Debug.Assert(NestedTypes is null ||
NestedTypes.OrderBy(t => t.Name, StringComparer.Ordinal).Distinct());
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Distinct
returns an enumerable...
But we can indeed compare counts.
Fixes #53865
The issue is that we're collecting synthesized nested types into concurrent queues but adding them in a non-deterministic order.
The two code paths below compete to add those nested types and include tasks/threads when not under a debugger (tests turn off concurrency when debugged).
The result was that those nested types didn't always appear in the same order in metadata.