Live data from Hacker News

Strings and the CLR – A Special Relationship

mattwarren.org

1–10 of 30 posts

Re: Strings and the CLR – A Special Relationship

#2
Another point for this, besides optimization, is easier interop with existing technologies. The memory layout is identical to Windows' BSTR, as far as I know, and also includes a terminating U+0000. All of that makes it possible to marshal a CLR string as is in many circumstances without the need to copy or convert the characters around.

Re: Strings and the CLR – A Special Relationship

#3
Before the CLR was open sourced you could investigate how things were implemented by using decompilers on the MSIL code or later shared source, but but investgations often stopped at a InternalCall just as things started to get interesting. Now you can see the whole story of how abstractions are implemented part in C# and part in C++ when the runtime needs to "bend the rules" of what C# would normally allow. The corert[0] project is interesting because a larger portion of the run is implemented in C# (or as compilation passes instead of runtime code generation). For example, you can find exception dispatch and type casting implemented in C# there [1].

One example from the article that may be a little off is getting the length of string. It looks like the call to string.get_Length is probably replaced with a JIT intrinsic[2]. The importer then turns that intrinsic call into a GT_ARR_LENGTH[3] node that is eventually lowered into something like[4]:

    *(stringAddr + offsetOfStringLengthField)
It's a bit more complicated than that, as there are several references to GT_ARR_LENGTH in various optimization passes.

[0]: https://github.com/dotnet/corert/ [1]: https://github.com/dotnet/corert/tree/master/src/Runtime.Bas... [2]: https://github.com/dotnet/coreclr/blob/a123c3972c447c8bcfa18... [3]: (warning, big file) https://github.com/dotnet/coreclr/blob/a123c3972c447c8bcfa18... [4]: (warning, big file) https://github.com/dotnet/coreclr/blob/a123c3972c447c8bcfa18...

Re: Strings and the CLR – A Special Relationship

#4
post #2

Another point for this, besides optimization, is easier interop with existing technologies. The memory layout is identical to Windows' BSTR, as far as I know, and also includes a terminating U+0000. All of that makes it possible to marshal a CLR string as is in many circumstances without the need to copy or convert the characters around.

There is an amusing comment in the CLR about it's support for odd length BSTRs[0]. There can be an extra wchar after the null terminator to store the extra byte.

It looks like if you use the automatic BSTR marshaler it creates a copy[1], though the CLR is so big it's hard for me to say that with confidence. Taking the address of a string with the fixed statement in C# of course won't allocate and that pointer can be passed to APIs that expected Unicode strings.

[0]: https://github.com/dotnet/coreclr/blob/a123c3972c447c8bcfa18... [1]: https://github.com/dotnet/coreclr/blob/a123c3972c447c8bcfa18...

Re: Strings and the CLR – A Special Relationship

#5

Before the CLR was open sourced you could investigate how things were implemented by using decompilers on the MSIL code or later shared source, but but investgations often stopped at a InternalCall just as things started to get interesting. Now you can see the whole story of how abstractions are implemented part in C# and part in C++ when the runtime needs to "bend the rules" of what C# would normally allow. The core…

Not necessarily. As long as it wasn't related to the JIT or the GC, one could always look up the SSCLI (ROTOR) code to understand how something was implemented. https://en.wikipedia.org/wiki/Shared_Source_Common_Language_...

Re: Strings and the CLR – A Special Relationship

#7
post #6

So, are there high-level languages that make it easy to write classes that include length-varies-by-instance member(s) in their memory layout? That could be a huge efficiency gain because of cache misses.

Smalltalk has that:

https://www.gnu.org/software/smalltalk/manual-base/html_node...

https://www.gnu.org/software/smalltalk/manual/html_node/Insi...

Although see the footnote - "This is not always true for other Smalltalk implementations, who don't allow instance variables in variableByteSubclasses and variableWordSubclasses". So, in some implementations, you can have either normal fields or array slots, but not both. That said, i think if you have a base class with fields, you can always make a subclass with slots.

Re: Strings and the CLR – A Special Relationship

#8
post #5

Before the CLR was open sourced you could investigate how things were implemented by using decompilers on the MSIL code or later shared source, but but investgations often stopped at a InternalCall just as things started to get interesting. Now you can see the whole story of how abstractions are implemented part in C# and part in C++ when the runtime needs to "bend the rules" of what C# would normally allow. The core…

Not necessarily. As long as it wasn't related to the JIT or the GC, one could always look up the SSCLI (ROTOR) code to understand how something was implemented. https://en.wikipedia.org/wiki/Shared_Source_Common_Language_...

That's a good point. It's fun to diff Rotor and CoreCLR to see how much has changed and what has stayed the same. The JIT and GC seem to not match up at all, but good chunks of the vm folder match up nicely.

Re: Strings and the CLR – A Special Relationship

#9

Before the CLR was open sourced you could investigate how things were implemented by using decompilers on the MSIL code or later shared source, but but investgations often stopped at a InternalCall just as things started to get interesting. Now you can see the whole story of how abstractions are implemented part in C# and part in C++ when the runtime needs to "bend the rules" of what C# would normally allow. The core…

> Before the CLR was open sourced you could investigate how things were implemented by using decompilers on the MSIL code or later shared source, but but investgations often stopped at a InternalCall just as things started to get interesting. Now you can see the whole story of how abstractions are implemented part in C# and part in C++ when the runtime needs to "bend the rules" of what C# would normally allow.

Yep, that's a large part of the motivation for me writing this post, although after looking at the source, I then went back to WinDBG and the Microsoft Symbol Server, which I could've done before it was open sourced!!

Thanks for the clarification on what the JIT is doing to optimise the string length. So far I've not managed to find the time to look at it's source, it took me long enough to find my way round CoreCLR!

In the post, I sort-of hand-waved about what was happening there, it's nice to have some more concrete details.

Re: Strings and the CLR – A Special Relationship

#10
post #2

Another point for this, besides optimization, is easier interop with existing technologies. The memory layout is identical to Windows' BSTR, as far as I know, and also includes a terminating U+0000. All of that makes it possible to marshal a CLR string as is in many circumstances without the need to copy or convert the characters around.

Yeah that's a good point, I completely steered clear from talking about marshalling and/or interop (mostly due to lack of time), maybe I'll do a Part 2 and include that.
Post reply on HN