Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 93 стр.

UptoLike

GenExpr[Expr1],
GenExpr[Expr2],
dup,
stloc временная переменная,
stfld f,
ldloc временная переменная;
GenExpr[Expr call s ArgList] =
GenExpr[Expr],
GenArgList[ArgList],
call(callvirt) s;
GenArgList[Expr ArgList] =
GenExpr[Expr],
GenArgList[ArgList];
GenArgList[пусто] = ;
GenBinOp[plus] = add;
GenBinOp[minus] = sub;
GenBinOp[mul] = mul;
GenBinOp[div] = div;
5.2.2. Оптимизация линейных участков кода
Зачастую бывает удобно разделить фазы генерации и оптимизации
кода. Это позволяет существенно упростить генератор, сделать его незави-
симым от оптимизатора и, кроме того, повторно использовать оптимиза-
тор с другими генераторами.
Существует большое количество методов оптимизации, но в контек-
сте динамической генерации кода, требующей быстрой работы оптимиза-
тора, не все эти методы применимы. Поэтому мы рассмотрим один из са-
мых простых методов – так называемую peephole-оптимизацию.
Суть peephole-оптимизации заключается в том, что оптимизатор
ищет в коде метода сравнительно короткую последовательность инструк-
ций, удовлетворяющую некоторому образцу, и заменяет ее более эффек-
тивной последовательностью инструкций.
Алгоритм peephole-оптимизации использует понятие фрейма. Фрейм
можно представить как окошко, двигающееся по коду метода. Содержи-
мое фрейма сравнивается с образцом, и в случае совпадения выполняется
преобразование (см. рис. 5.1).
Peephole-оптимизация линейного участка кода должна выполняться
многократно до тех пор, пока на очередном проходе фрейма по этому уча-
стку кода не будет найдено ни одного образца. С другой стороны, алго-
ритм peephole-оптимизации может быть остановлен в любой момент, что
позволяет добиться требуемой скорости работы оптимизатора.
Динамическая генерация кода
173
5.2.1.2. Отображение абстрактного синтаксиса выражений в CIL
Определим набор функций, отображающих различные деревья абст-
рактного синтаксиса в соответствующие им последовательности инструк-
ций CIL.
Будем считать, что каждая функция принимает в качестве параметра
дерево абстрактного синтаксиса (оно записывается в квадратных скобках)
и возвращает последовательность инструкций (при этом запятые обозна-
чают операцию объединения последовательностей):
GenExpr[const c] = нужный вариант инструкции ldc;
GenExpr[local x] = ldloc x;
GenExpr[arg x] = ldarg x;
GenExpr[Expr1 index Expr2] =
GenExpr[Expr1],
GenExpr[Expr2],
ldelem.нужный тип;
GenExpr[Expr field f] =
GenExpr[Expr],
ldfld f;
GenExpr[minus Expr] =
GenExpr[Expr],
neg;
GenExpr[Expr1 BinOp Expr2] =
GenExpr[Expr1],
GenExpr[Expr2],
GenBinOp[BinOp];
GenExpr[local x assign Expr] =
GenExpr[Expr],
dup,
stloc x;
GenExpr[arg x assign Expr] =
GenExpr[Expr],
dup,
starg x;
GenExpr[Expr1 index Expr2 assign Expr3] =
GenExpr[Expr1],
GenExpr[Expr2],
GenExpr[Expr3],
dup,
stloc временная переменная,
stelem.нужный тип,
ldloc временная переменная;
GenExpr[Expr1 field f assign Expr2] =
172
CIL и системное программирование в Microsoft .NET
172                        CIL и системное программирование в Microsoft .NET   Динамическая генерация кода                                          173


5.2.1.2. Отображение абстрактного синтаксиса выражений в CIL                          GenExpr[Expr1],
     Определим набор функций, отображающих различные деревья абст-                    GenExpr[Expr2],
рактного синтаксиса в соответствующие им последовательности инструк-                  dup,
ций CIL.                                                                              stloc временная переменная,
     Будем считать, что каждая функция принимает в качестве параметра                 stfld f,
дерево абстрактного синтаксиса (оно записывается в квадратных скобках)                ldloc временная переменная;
и возвращает последовательность инструкций (при этом запятые обозна-                GenExpr[Expr call s ArgList] =
чают операцию объединения последовательностей):                                       GenExpr[Expr],
     GenExpr[const c] = нужный вариант инструкции ldc;                                GenArgList[ArgList],
     GenExpr[local x] = ldloc x;                                                      call(callvirt) s;
     GenExpr[arg x] = ldarg x;
     GenExpr[Expr1 index Expr2] =                                                   GenArgList[Expr ArgList] =
        GenExpr[Expr1],                                                               GenExpr[Expr],
        GenExpr[Expr2],                                                               GenArgList[ArgList];
        ldelem.нужный тип;                                                          GenArgList[пусто] = ;
     GenExpr[Expr field f] =                                                        GenBinOp[plus] = add;
        GenExpr[Expr],                                                              GenBinOp[minus] = sub;
        ldfld f;                                                                    GenBinOp[mul] = mul;
     GenExpr[minus Expr] =                                                          GenBinOp[div] = div;
        GenExpr[Expr],
        neg;
                                                                               5.2.2. Оптимизация линейных участков кода
     GenExpr[Expr1 BinOp Expr2] =                                                   Зачастую бывает удобно разделить фазы генерации и оптимизации
        GenExpr[Expr1],                                                        кода. Это позволяет существенно упростить генератор, сделать его незави-
        GenExpr[Expr2],                                                        симым от оптимизатора и, кроме того, повторно использовать оптимиза-
        GenBinOp[BinOp];                                                       тор с другими генераторами.
     GenExpr[local x assign Expr] =                                                 Существует большое количество методов оптимизации, но в контек-
        GenExpr[Expr],                                                         сте динамической генерации кода, требующей быстрой работы оптимиза-
        dup,                                                                   тора, не все эти методы применимы. Поэтому мы рассмотрим один из са-
        stloc x;                                                               мых простых методов – так называемую peephole-оптимизацию.
     GenExpr[arg x assign Expr] =                                                   Суть peephole-оптимизации заключается в том, что оптимизатор
        GenExpr[Expr],                                                         ищет в коде метода сравнительно короткую последовательность инструк-
        dup,                                                                   ций, удовлетворяющую некоторому образцу, и заменяет ее более эффек-
        starg x;                                                               тивной последовательностью инструкций.
     GenExpr[Expr1 index Expr2 assign Expr3] =                                      Алгоритм peephole-оптимизации использует понятие фрейма. Фрейм
        GenExpr[Expr1],                                                        можно представить как окошко, двигающееся по коду метода. Содержи-
        GenExpr[Expr2],                                                        мое фрейма сравнивается с образцом, и в случае совпадения выполняется
        GenExpr[Expr3],                                                        преобразование (см. рис. 5.1).
        dup,                                                                        Peephole-оптимизация линейного участка кода должна выполняться
        stloc временная переменная,                                            многократно до тех пор, пока на очередном проходе фрейма по этому уча-
        stelem.нужный тип,                                                     стку кода не будет найдено ни одного образца. С другой стороны, алго-
        ldloc временная переменная;                                            ритм peephole-оптимизации может быть остановлен в любой момент, что
     GenExpr[Expr1 field f assign Expr2] =                                     позволяет добиться требуемой скорости работы оптимизатора.