Составители:
Рубрика:
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] = позволяет добиться требуемой скорости работы оптимизатора.
Страницы
- « первая
- ‹ предыдущая
- …
- 91
- 92
- 93
- 94
- 95
- …
- следующая ›
- последняя »