runtime: IndexOutOfRangeException in System.Numerics.Vector(array) Where array Size < 32 Bytes

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.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 2
  • Comments: 46 (44 by maintainers)

Commits related to this issue

Most upvoted comments

@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.

[Intrinsic]

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 Compiler::impIntrinsic in https://github.com/dotnet/coreclr/blob/master/src/jit/importer.cpp has details how these intrinsic methods are recognized and expanded in the JIT.

*.Portable.cs conventions

https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/project-guidelines.md#code-file-naming-conventions applied to System.Memory project.

System.Private.CoreLib.sln .net side

@JeremyKuhne and I talked about this yesterday. @JeremyKuhne Could you please share your plans to make this more straightforward once you have them?

I’m stuck whether to document the exception thrown when the length of the array is less than Count.

Yes, it is fine to document the current behavior for exception thrown by Vector<T> constructors. Vector<T> constructors do not follow the framework design guidelines for performance reasons. Another difference from the standard is that they throw NullReferenceException (vs. the ArgumentNullException recommended by the framework design guidelines).

For the new exception message "At least {0} element(s) are expected in the parameter “{1}” defined in src/mscorlib/Resources/Strings.resx how would ComPlusThrow provide the parameters (am unable to find similar instances) and how will the C# type of format string (containing placeholders such as {0}) be parsed into native C++ style format string that will have %d and %s respectively?

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

  IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD      "AppDomain cannot be unloaded because the thread '%1' cannot be unwound out of it."

@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.

@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 😅

Another piece of code to dive into is here:

https://github.com/dotnet/coreclr/blob/aaafa705f6aa930343061a0753928839b1e75bf2/src/jit/simd.cpp#L2647-L2664

What is interesting this are types of checks as above SCK_RNGCHK_FAIL and SCK_ARG_EXCPN

@WinCPP JIT uses a GenTreeBoundsChk IR (with GT_SIMD_CHK oper) to throw the exception.

https://github.com/dotnet/coreclr/blob/aaafa705f6aa930343061a0753928839b1e75bf2/src/jit/simd.cpp#L2886-L2906

I guess this change may need to add a new value in enum SpecialCodeKind because the current SCK_RNGCHK_FAIL has the fixed error message.

Seems like my changes to the ‘tt’ file and the corresponding auto-generated file that has compiled into the assembly aren’t being picked up.

The implementation of [Intrinsics] methods is duplicated in the JIT. The code in .cs files is just a fallback for cases where the JIT intrinsic expansion does not kick in (e.g. when the method is called via reflection, or on platforms where the SIMD intrinsics are not implemented yet). It means that the change of exception message has to be done in the JIT to make it actually kick in.

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.