Add reference to .NET Memory Model#367
Conversation
Add reference to .NET Memory Model for clarity on memory safety.
|
|
||
| * Memory safety | ||
| * No access to uninitialized memory | ||
| * The [.NET Memory Model](https://github.com/dotnet/runtime/blob/main/docs/design/specs/Memory-model.md) |
There was a problem hiding this comment.
Should we have a sub-bullet for "language specific memory model additions"?
i.e. C# (abstract language) has its own memory model that is disconnected from .NET, then Roslyn (specific implementation of the language targeting .NET) has potential addendums to the language. So safe C# code also needs to respect any such stipulations or variants in there.
The same would apply to safe F# targeting other safe F#, etc.
We can't really easily define the bounds for interlanguage interop (i.e. C# calling F# or vice versa), but I think we could call out that within a single language and we expect languages to at least be compatible with the .NET memory model
|
|
||
| * Memory safety | ||
| * No access to uninitialized memory | ||
| * The [.NET Memory Model](https://github.com/dotnet/runtime/blob/main/docs/design/specs/Memory-model.md) |
There was a problem hiding this comment.
This doc explains the expected behavior of memory access (in the presence of multithreading). I am not sure what it means for the .NET code to be valid with respect to the properties explained in this doc. I think the most immediate interpretation of this statement would be that we want to guarantee race conditions free code, but that's not what we are doing here.
There was a problem hiding this comment.
Alternative proposals - add the following towards the end of "Global invariants" chapter:
These properties interact with other .NET runtime behaviors, such as .NET Memory Model. For example, it is invalid for safe code to be able to trigger undefined behavior caused by misaligned memory accesses.
There was a problem hiding this comment.
The linked doc explains the guaranteed behaviors of managed code. These are properties that must be maintained by all unsafe code. For example, the doc says:
Managed references are always aligned to their size on the given platform and accesses are atomic.
If unsafe code is used to create a managed reference that is either unaligned or where access is not atomic, that would be invalid code and the unsafe code would be in error.
There was a problem hiding this comment.
Managed references are always aligned to their size on the given platform and accesses are atomic.
This talks about the alignment of storage for the managed reference. It does not talk about the location where the managed reference points to. For example, situation like this:
[StructLayout(LayoutKind.Explicit)]
ref struct S
{
[FieldOffset(1)]
ref byte x;
}
This is invalid type layout. The runtime will refuse to load this type, unsafe code won't help you to get around that.
There was a problem hiding this comment.
I agree, but isn't that something that should be in the .NET Memory model doc?
Basically, shouldn't there be a list of all the guaranteed properties in the .NET model, irrespective of the safety model? Or do you think that we should move all the guarantees into this document?
There was a problem hiding this comment.
A few different concerns:
- Misaligned byrefs are valid, but you need to be careful how they get dereferenced. For example, the following code is valid:
[StructLayout(LayoutKind.Explicit)]
ref struct S
{
[FieldOffset(1)]
int x;
}
S s = default;
ref int misaligned = ref s.x;
It works fine today, the ECMA-335 indirectly suggests that misaligned byrefs are fine through defining unaligned. prefix, the memory model doc does not prohibit it.
-
It should not be possible to created misaligned byrefs in safe code (a lot of interop would become invalid if we were to allow that). We will need to figure out how to make that happen.
-
Where to document invariants where memory safety and interop intersects: misaligned byrefs should not leak into safe code, handles should be treated like a memory, etc. I would start with documenting it the unsafe evolution spec. We can disperse and cross-link it later once we understand the complete picture.
There was a problem hiding this comment.
I put a basic draft of what the rules could look like, we can fill it in with whatever data we want.
I do think we have to think about ways that unsafe might produce unaligned refs though. For example,
ref struct S
{
ref int x;
}
Span<byte> arr = ...;
var s = Unsafe.As<byte, S>(ref arr[3]);Obviously the big problem there is a completely invalid pointer, but it's also misaligned
Add alignment requirement to .NET memory model section and update properties list.
|
|
||
| * Memory safety | ||
| * No access to uninitialized memory | ||
| * Alignment with the .NET Memory Model |
There was a problem hiding this comment.
.NET memory model is just one of many feature areas that the safe subset must be aligned with. I do not think it makes sense to single out the memory model here, without going into details of what "Alignment with the .NET Memory Model" actually means.
I have submitted #368 with my proposed edit that should address what you are trying to achieve here with better clarity.
All code should preserve the guarantees of the .NET memory model, therefore this should be in the list.