-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
IndexOutOfRangeException in System.Numerics.Vector<T>(array) Where array Size < 32 Bytes #24174
Comments
|
Perhaps an exception with more information would be useful then (ie expecting x bytes) IndexOutOfRangeException is a bit vague for first-time users of this library. EDIT: Alternatively, address https://github.com/dotnet/corefx/issues/23448 to improve the clarity of what constructor calls do. |
Normally I'd expect the constructor to throw an @CarolEidt, do you have any thoughts here? EDIT: @eerhardt just pointed me to the code. Looks intentional, but we do have validation so we could easily change the exception. Changing the exception type is a binary breaking change, not sure it's worth it. We should, however, update the message to explain the error condition. |
The issue is that the constructor that takes only an array calls into the constructor that takes an array and an index. So that's where the "index" in "IndexOutOfRangeException" comes from - Perhaps just adding an appropriate message to this exception would suffice? |
Adding a message seems like a sufficient solution to me |
Agreed. |
May I pick this up for the changes? To test how it works, I did some change to pass a string "myexception" to the constructor of I am not sure if I have followed correct step... Help appreciated. |
@WinCPP You need to build the T4 templates in Visual Studio, so it generates a new .cs file with the changes you made. For the tests, this may involve copying the ...includes.tt file to same directory as the test.tt file. Otherwise, Visual Studio will give you a build error when attempting to build the T4 templates in the solution. |
@clarkis117 Thanks. I am working on #23688 at this time and would like to take this up next. @clarkis117 Now I remember, that time I had done the changes to the tt file itself but found that the somehow the generic message in the |
The implementation of |
Is this something that I can do or is it offlimits for me...? I am interested... |
It is not one liner change, but I am sure that you would be able to do it if you dive into it. There is pretty active community around the JIT intrinsics ( @4creators @CarolEidt @eerhardt @fiigii @sdmaclea @tannergooding ) that I am sure will be happy to give you guidance as necessary. |
@WinCPP JIT uses a I guess this change may need to add a new value in |
Another piece of code to dive into is here: What is interesting this are types of checks as above |
@fiigii @4creators now taking a look into this. Thanks for inputs. |
@jkotas is there some docs on this?I mean [Intrinsic], *.Portable.cs conventions, debug System.Private.CoreLib etc...i'm very interested to go deeper and help more...but sometimes is a bit cryptic where put the hands(first reason coreclr/corefx are huge code bases with a lot of tecnologies...and this is amazing, the best school). For instance i like to work on System.Private.CoreLib.sln .net side but i haven't found on guide how to 'dev/attach debug' code for that part, i undestood that the tests are all on CoreFx so after write code we need to test with local build. Sorry to all for noise on this issue...but like @WinCPP i did some experiments with same results 😅 |
https://github.com/dotnet/coreclr/blob/master/src/mscorlib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs has the two line version of the documentation. Comment in front of
https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/project-guidelines.md#code-file-naming-conventions applied to System.Memory project.
@JeremyKuhne and I talked about this yesterday. @JeremyKuhne Could you please share your plans to make this more straightforward once you have them? |
@jkotas great!Thank you very much! |
@MarcoRossignoli this is the best we have at the moment: https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/developer-guide.md#testing-with-private-coreclr-bits We want to improve the process, so don't hesitate to provide feedback. You can add to the docs, create issues, whatever. Please feel free to tag me whenever you do. |
Ok @JeremyKuhne! thank's a lot for the infos! |
I studied the two places that @fiigii and @4creators mentioned. The first one (ref here) appears to be related indexed access on the array whereas the second one (ref here) appears to be related to initialization (
However, in Additionally, all these exceptions thrown as Appreciate inputs on whether I am on right track. |
It is defined via macros from https://github.com/dotnet/coreclr/blob/master/src/vm/rexcep.h |
Check the following places https://github.com/dotnet/coreclr/blob/b3ea3629f6ada693bd6db259485f87b7a8beb78d/src/utilcode/ex.cpp#L84-L99 and follow the logic It will specifically lead to The class CCompRC is used to access strings //*****************************************************************************
// CCompRC manages string Resource access for COM+. This includes loading
// the MsCorRC.dll for resources as well allowing each thread to use a
// a different localized version.
//*****************************************************************************
class CCompRC
{ |
With help of pointers provided above, I tried finding the code. The problem that I face is I'm unable to crack the link between For the new exception message Between, quick check - is this issue no more within the realm of 'up-for-grabs' and am I consuming too many cycles of yours? If not then I am interested to continue... Thanks! |
@WinCPP I don't know the best way, but I open this in VS: C:\git\coreclr\bin\obj\Windows_NT.x64.Debug\src\vm\wks\cee_wks.vcxproj The vcxproj's are generated by CMake during the build. |
COMPlusThrow takes up to 6 extra args eg COMPlusThrow(kCannotUnloadAppDomainException,
IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD,
sThreadId); in this case the resource is in C:\git\coreclr\src\dlls\mscorrc\mscorrc.rc
|
|
Similar way in VS Code is to use search with functionName or in Visual Studio open |
@danmosemsft
Please let me rephrase my question. Currently following exception is thrown which defined in src/mscorlib/Resources/Strings.resx#L373-375 and not in src/dlls/mscorrc/mscorrc.rc.
Essentially JITter appears to be sourcing the exception string from a managed resource bundle, but this string doesn't have parameter placeholders. The new more descriptive exception message with placeholders for minimum element count is already defined here in managed resource file. |
hmm and further I'm trying to figure out the place where the IR sub-tree generated by Between, this appears to be different from the "app domain unload" exception case discussed above, because that appears to be directly thrown from the compiled code in JIT and not related to on-the-fly compiled (JITted) code. I guess the code generation code that I am interested in is in src\jit\codegenxarch.cpp...? EDIT 1: I think I got it... it is |
Incidentally, |
Few days back, for issue dotnet/corefx#24343 (PR dotnet/coreclr#16733) I added the following new exception to be thrown in <data name="Arg_InsufficientNumberOfElements" xml:space="preserve">
<value>At least {0} element(s) are expected in the parameter "{1}".</value>
</data> To include the index and the length, are we looking to have message such as |
@WinCPP I think the existing string is very famliar to developers' eyes so I would change it only a little <data name="Arg_IndexOutOfRangeExceptionWithValue" xml:space="preserve">
<value>Index {0} was outside the bounds of the array of length {1}.</value>
</data> This does not need to be in this PR. Fully eliminating the old string might take some time/several PR's. |
True. But I thought the ask in this issue (opening few comments) was to give at information as to how many number of elements are expected (should be present at the minimum) in the source... And the index throws a spinner as then the minimum number of elements in the source should be with respect to the index... |
Fair enough |
If you do this throughout the framework, you are going to bloat the code quite a bit and likely introduce number of performance regressions in the process. We should understand the value we would be adding by doing so. It is pretty rare to be able to diagnose the index out of range exception by just looking at the bad index. You typically need to know the larger context, so I doubt that knowing the value of the bad index would improve diagnostic experience significantly. |
Alright -- makes sense -- disregard my suggestion ... 😃 |
Hi. I think I have figured out how to pass the void CodeGen::genJumpToThrowHlpBlk(emitJumpKind jumpKind, SpecialCodeKind codeKind, GenTree* indexTree, GenTree* failBlk = nullptr) // note the additional 3rd argument indexTree Idea is to traverse the getEmitter()->emitIns_I(INS_push, EA_4BYTE, vectorLength);
genSinglePush();
args += REGSIZE_BYTES; However, I am not sure how to handle the "throw block reuse" in the function I hope I am on right tracks. Inputs appreciated. |
I think It tends to be complex and fragile to generate complex intrinsic expansions in the JIT like what you are trying to do here. You may look at this from other direction. Make the Vector constructor non-intriniscs, like:
And then see whether we are losing any optimizations if you do this. If we are losing any optimizations with non-intrinsic implementation like this, look at what needs to be done to get them back. |
@jkotas Thanks for the inputs. Need some guidance around this line.
Do you mean performance data or you mean the generated IL code, etc.? I haven't done that earlier and hence some inputs around what I have to inspect (and perhaps the tools) will help me a lot and would give me an opportunity to learn something new. Thanks! |
I meant generated native code. It is where any missing optimizations are going to show up. Here is what you can try to do:
Alternatively, you can use tools like http://adamsitnik.com/Disassembly-Diagnoser/ . Or just look at the native code using native debugger. |
Hi @jkotas, resuming after considerable time. I did the following,
But still the call to the JIT exception throw method
Not sure if this is correct way. Appreciate your advice. EDIT 1: I am working on Windows 10 x64 machine. Is this some issue of netcoreapp vs some other type of build that I should be using...? |
Try generating the jit log for the method using |
Hi all. Want to keep you updated that I'm not getting cycles to do this one at this point in time. Apologies. |
I wonder what is the design decision here, whether |
Yes, it is fine to document the current behavior for exception thrown by Vector constructors. |
System.Numerics.Vector<byte> vec = new System.Numerics.Vector<byte>(new byte[] { 4, 3, 2, 1, 6, 4, 2, 4 });
This call will crash with an
IndexOutOfRangeException
exception. I'm pulling in this library as a NuGet package. If I pass in >= 32 bytes, this code works.The same logic applies to other data types if they do not fill enough at least 32 bytes.
Is there a reason for this behavior? My use case involves passing variable length bytes (anywhere from 1 to millions). The constructor does not make this behavior clear, and I'd prefer to not have to pad my byte arrays to use this.
If the library is not supposed to support values less than the size of the XMM/YMM register, then it would be ideal to at least throw a more specific exception.
The text was updated successfully, but these errors were encountered: