Unity-Technologies/mono — pull request #185 by joshpeterson (2014-12-30 16:25:51+00:00)
Title: Work around a bug in the isinst opcode

This a description of a bug in our version of Mono related to isinst
for array types. The following snippet of code demonstrates the bug:

byte[] byteArray = new byte[2];
Array test = byteArray;
var isSByteArray = test is sbyte[];
var isByteArray = test is byte[];

Console.WriteLine("byte[] is sbyte[]: {0}", isSByteArray);
Console.WriteLine("byte[] is byte[]: {0}", isByteArray);

Here is the run time behavior for

.Net:

e:\unity>E:\scratch\ScratchCSharpProject\ScratchCSharpProject\bin\x64\De
bug\ScratchCSharpProject.exe
byte[] is sbyte[]: True
byte[] is byte[]: True

MonoBleedingEdge:

e:\unity>e:\unity\build\WindowsEditor\Data\MonoBleedingEdge\bin\mono
E:\scratch\ScratchCSharpProject\ScratchCSharpProject\bin\x64\Debug\Scrat
chCSharpProject.exe
byte[] is sbyte[]: True
byte[] is byte[]: True

Our Mono:

e:\unity>e:\unity\build\WindowsEditor\Data\Mono\bin\mono
--runtime=v2.0.50727
E:\scratch\ScratchCSharpProject\ScratchCSharpProject\bin\x64\Debug\Scrat
chCSharpProject.exe
byte[] is sbyte[]: False
byte[] is byte[]: True

Notice that out Mono returns false in the first case. This incorrect
behavior causes the code in MonoEnumInfo.GetInfo to behave correctly.
The code from GetInfo looks like this:

get_enum_info (enumType, out info);

IComparer ic = null;
if (info.values is int [])
ic = int_comparer;
else if (info.values is short [])
ic = short_comparer;
else if (info.values is sbyte [])
ic = sbyte_comparer;
else if (info.values is long [])
ic = long_comparer;

Array.Sort (info.values, info.names, ic);

For a byte Enum, info.values is actually a byte[], and the code here
expects all of these if statements to be false, leaving ic equal to
null for the Array.Sort call. If the third if statement returns true
(as it should to match .Net and MonoBleedingEdge), we will use the
sbyte_comparer, which will cause an InvalidCastException to be thrown
when it attempts to unbox a byte as an sbyte. Since we want to leave
the IL2CPP behavior matching the .Net and MonoBleedingEdge behavior, as
it does now, this change worksaround the bug in is inst.

We first check explicitly for the unsigned array types, and leave ic
equal to null in those cases. Tests for this behavior will be committed
to the Unity code, both in the IL2CPP unit tests and in Unity runtime
tests.