Я хотел бы улучшить лямбда-код, сгенерированный для конструкции "assert" OCaml 3.12.1. Вот пример:
let f x =
assert (x = 4);
assert (2 + x = 6);
assert (x - x = 0);
exit x
Файл longfilename.ml, приведенный выше, является представителем больших модулей OCaml, для которых я хотел бы улучшить генерацию лямбда-кода. Он компилируется в:
$ ocamlopt -S longfilename.ml
$ cat longfilename.s
...
.data
.quad 3072
_camlLongfilename__2:
.quad L100007
.quad 9
.quad 9
.quad 2300
L100007: .L100007:
.ascii "longfilename.ml"
.byte 0
.data
.quad 3072
_camlLongfilename__3:
.quad L100006
.quad 7
.quad 9
.quad 2300
L100006: .L100006:
.ascii "longfilename.ml"
.byte 0
.data
.quad 3072
_camlLongfilename__4:
.quad L100005
.quad 5
.quad 9
.quad 2300
L100005: .L100005:
.ascii "longfilename.ml"
.byte 0
...
Вышеупомянутое ужасно избыточно. Имя исходного файла, из которого может исходить каждое утверждение, дублируется. Похоже, что виновником является bytecomp/translcore.ml:
let assert_failed loc =
(* [Location.get_pos_info] is too expensive *)
let fname = match loc.Location.loc_start.Lexing.pos_fname with
| "" -> !Location.input_name
| x -> x
in
let pos = loc.Location.loc_start in
let line = pos.Lexing.pos_lnum in
let char = pos.Lexing.pos_cnum - pos.Lexing.pos_bol in
Lprim(Praise, [Lprim(Pmakeblock(0, Immutable),
[transl_path Predef.path_assert_failure;
Lconst(Const_block(0,
[Const_base(Const_string fname);
Const_base(Const_int line);
Const_base(Const_int char)]))])])
;;
На первый взгляд, похоже, этого было бы достаточно, чтобы дать имя
Const_base(Const_string fname)
, а для хранения и повторного использования
хэш-таблицу времени компиляции. Для внутримодульной оптимизации,
изменения просто могут быть управляемы
(пока хэш-таблица reset в каждом блоке компиляции).
Я немного из глубины здесь, особенно "reset на каждой компиляции единица ". Любой намек?