改进lambda代码OCaml会产生断言

时间:2012-04-04 09:36:40

标签: ocaml

我想改进为“断言”OCaml 3.12.1构造生成的lambda代码。这是一个例子:

let f x =
    assert (x = 4);
    assert (2 + x = 6);
    assert (x - x = 0);
    exit x

上面的文件longfilename.ml代表了我希望改进lambda代码生成的大型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),并存储和重复使用它 编译时哈希表。对于模块内优化, 这些变化可能是可以控制的 (只要在每个编译单元重置哈希表)。

我有点超出我的深度,尤其是“每次编辑时重置” 单位“部分。任何提示?

1 个答案:

答案 0 :(得分:8)

OCaml编译器中已经有一种机制可以共享一些常量:请参阅asmcomp/compilenv.ml中的structured_constants及其使用,特别是asmcomp/cmmgen.ml值。Const_base (Const_string foo)。我不熟悉这段代码,所以我不确定为什么你的特定用例没有被共享,但似乎在lambda代码Const_immstring fooimmstring之间存在差异;后者是共享的,也许前者不是。

我不知道bytecomp/translclass.ml的预期语义是什么。它似乎在内部编译器用于编译方法标签(asmcomp/cmmgen.ml:emit_constant),但不会暴露给输入语言。

(我怀疑区别是因为字符串是可变的,因此共享用户可见的字符串将是可观察的并且改变程序行为。但字符串常量已经被提升,因此用户已经可以观察到语义上不一致的共享。增加用户的共享 - 可见字符串可能仍会因兼容性中断而被拒绝。)

看看这些直接字符串由常量发射代码(immstring)处理的方式,它们就像通常的字符串一样表示,所以也许你可以修改编译器以使用assert_failed in Const_base (Const_string fname)并且事情会奏效。

[编辑OP]

Const_immstring fname更改为$ cat longfilename.s ... .data .quad 3072 _camlLongfilename__2: .quad L100005 .quad 9 .quad 9 .data .quad 3072 _camlLongfilename__3: .quad L100005 .quad 7 .quad 9 .data .quad 3072 _camlLongfilename__4: .quad L100005 .quad 5 .quad 9 .quad 2300 L100005: .L100005: .ascii "longfilename.ml" .byte 0 虽然稍微不兼容,但允许OCaml自行编译,编译Frama-C并且新的Frama-C通过其回归测试。在原始示例中,效果如下,这正是所需的结果:

{{1}}