Составители:
Рубрика:
4.2.3. Присвоение родительских блоков узлам графа
На третьем этапе узлы, соответствующие инструкциям, получают ро-
дителей. Тем самым завершается построение дерева блоков.
Можно заметить, что все блоки графа, включая блок тела метода,
хранятся в массиве B. При этом порядок их следования в массиве таков,
что вложенные блоки размещаются перед объемлющими их блоками. Это
следует из того факта, что на втором этапе алгоритма блоки добавлялись в
массив в порядке, обратном их следованию в массиве предложений обра-
ботки исключений (EH).
Присвоение родительских блоков узлам графа заключается в том, что
мы перебираем все элементы массива B по порядку, начиная с первого эле-
мента (в нем содержится информация о блоке тела метода). При этом для
каждого i-го элемента массива B мы выполняем следующую операцию:
каждый узел графа, имеющий в массиве Nodes индекс от B[i].offset до
B[i].offset+B[i].length-1, получает в качестве родителя блок B[i].block.
for (int i = 0; i < BN; i++)
{
for (int j = B[i].offset; j < B[i].offset+B[i].length; j++)
Сделать блок B[i].block родителем узла Nodes[j];
}
Таким образом, на первой итерации цикла родителем всех узлов ста-
новится блок тела метода (MBB), а на последующих итерациях некоторые
диапазоны инструкций меняют родителей, и это происходит до тех пор,
пока не будут рассмотрены все элементы массива B. В конце концов роди-
телями всех узлов становятся именно те блоки, в которые эти узлы непо-
средственно входят.
4.2.4. Формирование дуг
На четвертом этапе в граф потока управления добавляются дуги, обо-
значающие передачу управления между инструкциями.
Определенную трудность представляет необходимость включения в
граф потока управления узлов-блоков. Предварительным шагом для этого
служит создание специального массива blockNodes размера N и запись в
этот массив ссылок на блоки. При этом запись осуществляется следую-
щим образом: мы перебираем все структуры в массиве B и для каждой
i-ой структуры записываем в элемент массива blockNodes с индексом
B[i].offset ссылку B[i].block. В результате, для того, чтобы определить,
какой блок начинается с инструкции с номером k, достаточно посмотреть
k-тый элемент массива blockNodes.
Формирование массива blockNodes удобно совместить с проведением
дуг от узлов-блоков к узлам, соответствующим первым инструкциям этих
Анализ кода на CIL
145
/* Поиск в массиве B блока, диапазон инструкций которого содержит
защищенную областью i-го предложения */
int tryOffset = EH[i].TryOffset, tryLength = EH[i].TryLength;
for (int j = BN-1; j >= 0; j--)
if (tryOffset >= B[j].offset &&
tryOffset+tryLength <= B[j].offset+B[j].length)
break;
if (tryOffset != B[j].offset || tryLength != B[j].length)
{
/* Создание нового защищенного блока и
добавление его в дерево */
B[BN].block = новый защищенный блок;
Сделать блок B[j].block родителем блока B[BN].block;
B[BN].offset = tryOffset;
B[BN].length = tryLength;
j = BN; BN++;
}
/* Создание блока обработки исключений */
B[BN].block = новый блок обработки исключений,
тип которого определяется значением EH[i].Flags;
Сделать родителем блока B[BN].block тот же блок,
который является родителем блока B[j].block;
Добавить блок B[BN].block в конец списка
обработчиков, ассоциированных с блоком B[j].block;
B[BN].offset = EH[i].HandlerOffset;
B[BN].length = EH[i].HandlerLength;
BN++;
if (EH[i].Flags обозначает блок с пользовательской фильтрацией)
{
/* Создание блока фильтрации */
B[BN].block = новый блок фильтрации;
Сделать блок B[BN-1].block родителем блока B[BN].block;
B[BN].offset = EH[i].FilterOffset;
B[BN].length = EH[i].HandlerOffset – EH[i].FilterOffset;
BN++;
}
}
144
CIL и системное программирование в Microsoft .NET
144 CIL и системное программирование в Microsoft .NET Анализ кода на CIL 145
/* Поиск в массиве B блока, диапазон инструкций которого содержит 4.2.3. Присвоение родительских блоков узлам графа
защищенную областью i-го предложения */
int tryOffset = EH[i].TryOffset, tryLength = EH[i].TryLength; На третьем этапе узлы, соответствующие инструкциям, получают ро-
for (int j = BN-1; j >= 0; j--) дителей. Тем самым завершается построение дерева блоков.
if (tryOffset >= B[j].offset && Можно заметить, что все блоки графа, включая блок тела метода,
tryOffset+tryLength <= B[j].offset+B[j].length) хранятся в массиве B. При этом порядок их следования в массиве таков,
break; что вложенные блоки размещаются перед объемлющими их блоками. Это
следует из того факта, что на втором этапе алгоритма блоки добавлялись в
if (tryOffset != B[j].offset || tryLength != B[j].length) массив в порядке, обратном их следованию в массиве предложений обра-
{ ботки исключений (EH).
/* Создание нового защищенного блока и Присвоение родительских блоков узлам графа заключается в том, что
добавление его в дерево */ мы перебираем все элементы массива B по порядку, начиная с первого эле-
B[BN].block = новый защищенный блок; мента (в нем содержится информация о блоке тела метода). При этом для
Сделать блок B[j].block родителем блока B[BN].block; каждого i-го элемента массива B мы выполняем следующую операцию:
B[BN].offset = tryOffset; каждый узел графа, имеющий в массиве Nodes индекс от B[i].offset до
B[BN].length = tryLength; B[i].offset+B[i].length-1, получает в качестве родителя блок B[i].block.
j = BN; BN++; for (int i = 0; i < BN; i++)
} {
for (int j = B[i].offset; j < B[i].offset+B[i].length; j++)
/* Создание блока обработки исключений */ Сделать блок B[i].block родителем узла Nodes[j];
B[BN].block = новый блок обработки исключений, }
тип которого определяется значением EH[i].Flags; Таким образом, на первой итерации цикла родителем всех узлов ста-
Сделать родителем блока B[BN].block тот же блок, новится блок тела метода (MBB), а на последующих итерациях некоторые
который является родителем блока B[j].block; диапазоны инструкций меняют родителей, и это происходит до тех пор,
Добавить блок B[BN].block в конец списка пока не будут рассмотрены все элементы массива B. В конце концов роди-
обработчиков, ассоциированных с блоком B[j].block; телями всех узлов становятся именно те блоки, в которые эти узлы непо-
B[BN].offset = EH[i].HandlerOffset; средственно входят.
B[BN].length = EH[i].HandlerLength;
BN++; 4.2.4. Формирование дуг
На четвертом этапе в граф потока управления добавляются дуги, обо-
if (EH[i].Flags обозначает блок с пользовательской фильтрацией) значающие передачу управления между инструкциями.
{ Определенную трудность представляет необходимость включения в
/* Создание блока фильтрации */ граф потока управления узлов-блоков. Предварительным шагом для этого
B[BN].block = новый блок фильтрации; служит создание специального массива blockNodes размера N и запись в
Сделать блок B[BN-1].block родителем блока B[BN].block; этот массив ссылок на блоки. При этом запись осуществляется следую-
B[BN].offset = EH[i].FilterOffset; щим образом: мы перебираем все структуры в массиве B и для каждой
B[BN].length = EH[i].HandlerOffset – EH[i].FilterOffset; i-ой структуры записываем в элемент массива blockNodes с индексом
BN++; B[i].offset ссылку B[i].block. В результате, для того, чтобы определить,
} какой блок начинается с инструкции с номером k, достаточно посмотреть
} k-тый элемент массива blockNodes.
Формирование массива blockNodes удобно совместить с проведением
дуг от узлов-блоков к узлам, соответствующим первым инструкциям этих
Страницы
- « первая
- ‹ предыдущая
- …
- 77
- 78
- 79
- 80
- 81
- …
- следующая ›
- последняя »
