-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Conversation
I think it should work. I'll capture this pattern in a test case and make sure. |
@@ -25,9 +25,11 @@ namespace System.Text | |||
[System.Runtime.InteropServices.ComVisible(true)] | |||
public class ASCIIEncoding : Encoding | |||
{ | |||
// Allow for devirtualization (see https://github.com/dotnet/coreclr/pull/9230) | |||
internal sealed class ASCIIEncodingSealed : ASCIIEncoding { } |
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: can you add a blank line below 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.
Also, do we need to do something for serialization?
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.
Ah, yes. The type will both need to be annotated add Serializable and have a serialization ctor added.
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 take that back. I thought the base types implemented ISerializable, but it doesn't look like they do. So just the attribute is fine.
internal sealed class UTF8EncodingSealed : UTF8Encoding | ||
{ | ||
public UTF8EncodingSealed() : base(encoderShouldEmitUTF8Identifier: true) { } | ||
} |
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: can you add a blank line below 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.
As long as it gets the expected benefits, LGTM.
Unfortunately we may not get this fully optimized in the first go-round, see notes over on #1166. |
Will close for now |
84972f9
to
b454610
Compare
Rebased and addressed feedback now #9230 has been merged |
@@ -23,9 +23,13 @@ namespace System.Text | |||
[Serializable] | |||
public class ASCIIEncoding : Encoding | |||
{ | |||
// Allow for devirtualization (see https://github.com/dotnet/coreclr/pull/9230) | |||
[Serializable] | |||
internal sealed class ASCIIEncodingSealed : ASCIIEncoding { } |
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: private?
@@ -53,9 +53,16 @@ public class UTF8Encoding : Encoding | |||
|
|||
private const int UTF8_CODEPAGE = 65001; | |||
|
|||
// Allow for devirtualization (see https://github.com/dotnet/coreclr/pull/9230) | |||
[Serializable] | |||
internal sealed class UTF8EncodingSealed : UTF8Encoding |
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: private?
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.
Its exposed via Encoding as
Encoding UTF8 => UTF8Encoding.s_default;
so it needs to be able to see the class; else s_default
being that type will be a compile error; if the s_default
field was UTF8Encoding
it might be too much of a stretch to infer it was actually UTF8EncodingSealed
as the type would have to store what it had actually been initialised to?
Don't know if the devirtualization extends to inspecting what a readonly static actually is?
Is it getting devirtualized as expected? Any resulting positive benefit on consumption? |
There is an example test case here that shows what works today. You can use |
Not sure; it is doing a lot of good stuff but not sure its picking this up
Digging a bit deeper |
Utf8String:ToString():ref:this doesn't seem to pick it up
With "target not direct"; going to try a few things. |
For Utf8String:ToString():ref:this -- presumably in crossgen -- the first time the jit sees the virtual call (in the importer) it can't devirtualize, and because of this it can't inline either:
but after the jit inlines the property getter, it gives devirtualization another try:
Unfortunately it is then tripped up because when prejitting it doesn't directly see the static field access. If this method were being jitted then late devirtualization would kick in. I'll have to add some more logic to handle the prejit case. Should not be too difficult to look through the IND and see if it is encapsulating a static field access, and if so, forward the type on to the devirtualization logic. |
If seal |
Ah ok, let me build an app |
I have a proof of concept for some of the prejit static field cases. But it still gets hung up when I use the code from this PR
If I modify the code so the static field has the sealed type internal sealed class Sealed : UTF8Encoding {
internal Sealed() : base(encoderShouldEmitUTF8Identifier: true)
{
}
}
// Used by Encoding.UTF8 for lazy initialization
internal static readonly Sealed s_default = new Sealed(); then we finally devirtualize during prejitting:
The challenge on the jit side is that |
@AndyAyersMS @stephentoub Yes it does pick it up later as runtime jit (in ASP.NET Kestrel)
|
Can't measure any perf impact currently as am running a bit of a zombie build to work with the latest coreclr/corefx |
Is more needed for this? It is getting devirtualized correctly |
See: https://github.com/dotnet/coreclr/issues/1166#issuecomment-276251559 and #9230
@AndyAyersMS would this approach work?