You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[JIT] Redundant Span<> bounds check not elided for fields in ref structs #10645
Range check elimination is rather conservative when type fields are involved (due to thread safety issues), it works best with local variables. Try copying _colStart to a local variable:
I can give it a try to see if that is the cause, but it is a field in a ref readonly struct so it would be safe for the JIT to assume it will not be changing without needing a copy.
readonly is not of much use sine it's pretty easy to workaround it, much like C++'s const. ref struct is more interesting, such struct live only on the stack so it would seem that they should not have thread safety issues. But I don't think thread safety is actually guaranteed, it's still possible to take the address of such a struct and somehow pass it to another thread. That's likely extremely rare but not impossible.
As I recall, part of the reasoning for making Span stack only was that the resulting implicit thread-safety would prevent struct tearing, so would it not also be okay to make that assumption for bounds check elimination? (And for that matter, does not the bounds check itself rely upon it?)
As I recall, part of the reasoning for making Span stack only was that the resulting implicit thread-safety would prevent struct tearing, so would it not also be okay to make that assumption for bounds check elimination?
Right, I need to double check that but it's quite possible that any means that would allow concurrent access to a stack location involve unsafe code. In that case it would probably reasonably for the JIT to assume that ref structs are never modified by other threads.
And for that matter, does not the bounds check itself rely upon it?
Bounds check optimizations assume that fields can be modified by other threads and the JIT doesn't do anything special in the case of ref structs. It used to be the case that bounds check elimination also worked in some cases that involved fields due to CSE but there was a bug in this area and its fix likely made the optimization more conservative.
Right, I need to double check that but it's quite possible that any means that would allow concurrent access to a stack location involve unsafe code.
Yep, it's impossible for code that escapes a pointer to a stack location to another thread to be safe. Not because the ECMA spec says so but simply because it's impossible to guarantee that the other thread won't attempt to dereference the pointer after the method that owns the stack location has returned.
And ECMA does indeed prevent verifiability by placing restrictions such as requiring stfld not to be an unmanaged pointer.
So it does look like the JIT could be less conservative when dealing with fields of ref structs.
changed the title [-][JIT] Redundant Span<> bounds check not elided immediately after length check[/-][+][JIT] Redundant Span<> bounds check not elided for fields in ref structs[/+]on Jul 9, 2018
Activity
mikedn commentedon Jul 9, 2018
Range check elimination is rather conservative when type fields are involved (due to thread safety issues), it works best with local variables. Try copying
_colStartto a local variable:Zhentar commentedon Jul 9, 2018
I can give it a try to see if that is the cause, but it is a field in a
ref readonlystruct so it would be safe for the JIT to assume it will not be changing without needing a copy.mikedn commentedon Jul 9, 2018
readonlyis not of much use sine it's pretty easy to workaround it, much like C++'sconst.ref structis more interesting, such struct live only on the stack so it would seem that they should not have thread safety issues. But I don't think thread safety is actually guaranteed, it's still possible to take the address of such a struct and somehow pass it to another thread. That's likely extremely rare but not impossible.Zhentar commentedon Jul 9, 2018
As I recall, part of the reasoning for making Span stack only was that the resulting implicit thread-safety would prevent struct tearing, so would it not also be okay to make that assumption for bounds check elimination? (And for that matter, does not the bounds check itself rely upon it?)
mikedn commentedon Jul 9, 2018
Right, I need to double check that but it's quite possible that any means that would allow concurrent access to a stack location involve unsafe code. In that case it would probably reasonably for the JIT to assume that ref structs are never modified by other threads.
Bounds check optimizations assume that fields can be modified by other threads and the JIT doesn't do anything special in the case of ref structs. It used to be the case that bounds check elimination also worked in some cases that involved fields due to CSE but there was a bug in this area and its fix likely made the optimization more conservative.
mikedn commentedon Jul 9, 2018
Yep, it's impossible for code that escapes a pointer to a stack location to another thread to be safe. Not because the ECMA spec says so but simply because it's impossible to guarantee that the other thread won't attempt to dereference the pointer after the method that owns the stack location has returned.
And ECMA does indeed prevent verifiability by placing restrictions such as requiring
stfldnot to be an unmanaged pointer.So it does look like the JIT could be less conservative when dealing with fields of
ref structs.Somewhat related to #9512.
[-][JIT] Redundant Span<> bounds check not elided immediately after length check[/-][+][JIT] Redundant Span<> bounds check not elided for fields in ref structs[/+]RussKeldorph commentedon Jul 10, 2018
@dotnet/jit-contrib @CarolEidt