Здравствуйте, vdimas, Вы писали:
Интереса ради разобрал ассемблер по ссылке:
// выделили память на стеке (что-то дохрена)
L0000: sub rsp, 0x28
// в rcx пришло this
// rax=_indicies.Pointer (i.e. Bunch<int>._data0)
L0004: lea rax, [rcx+8]
// r8d = _indicies.Length
L0008: mov r8d, [rcx]
// for(i = 0;
L000b: xor r9d, r9d
L000e: jmp short L0013
// ===================== начало цикла ==============
// i++
L0010: inc r9d
// ? i < indices.Length
L0013: cmp r9d, r8d
// выход из цикла по i==indicies.Length
L0016: jge short L0021
// лишнее преобразование... всё-таки, в x64 Span.Length должно быть int64, т.е. nint.
L0018: movsxd r10, r9d
// ? indices[i] <= index
// здесь соптимизирована проверка выхода за границы при вызове indices[i]
L001b: cmp [rax+r10*4], edx
// зацикливание
L001f: jle short L0010
// =================== конец цикла ===================
// return (Children[i], i > 0 ? index - indices[i - 1] : index); L0021: lea r10, [rcx+0x48]
// r10=_children.Pointer
L0021: lea r10, [rcx+0x48]
// ecx = indices.Length (хотя, это значение сидит в r8d)
L0025: mov ecx, [rcx]
// проверили выход за массив Children[i]
L0027: cmp r9d, ecx
L002a: jae short L005f
// rcx=Childer[i]
L002c: movsxd rcx, r9d
L002f: mov rcx, [r10+rcx*8]
// ? i > 0
L0033: test r9d, r9d
L0036: jg short L003a
L0038: jmp short L004e
// r10d = i-1
L003a: lea r10d, [r9-1]
// проверка выхода за диапазон indices[i - 1] (как глупо)
L003e: cmp r10d, r8d
L0041: jae short L005f
// r8 = i-1 (опять?)
L0043: lea r8d, [r9-1]
L0047: movsxd r8, r8d
// index - indices[i - 1]
L004a: sub edx, [rax+r8*4]
// return t.Node[i]
L004e: cmp [rcx], ecx
L0050: add rcx, 8
L0054: call BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].get_Item(Int32)
L0059: nop
L005a: add rsp, 0x28
L005e: ret
// выброс IndexOutOfRangeException
L005f: call 0x00007ffb4bfba5e0
L0064: int3
Целевой цикл вылизан по самое нимогу.
Остальное с огрехами.