2012-04-04 44 views
10

我想改進爲「assert」OCaml 3.12.1構造生成的lambda代碼。下面是一個例子:改進lambda代碼OCaml爲斷言生成

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),以及存儲和使用 編譯期一重用實時哈希表。對於模塊內優化, 所做的更改可能是可管理的 (只要在每個編譯單元中重置了散列表)。

我在這裏稍微超出了我的深度,尤其是「在每個編譯器重置 單元」部分。任何提示?

回答

8

OCaml編譯器中已經有一個機制來共享一些常量:請參見asmcomp/compilenv.ml及其用法,特別是structured_constants值,asmcomp/cmmgen.ml。我對這段代碼並不熟悉,所以我不確定爲什麼你的特定用例不被共享,但是在lambda代碼中,似乎有一個區別:Const_base (Const_string foo)Const_immstring foo;後者是共享的,也許前者不是。

我不知道immstring的預期語義是什麼。它似乎被編譯器內部用來編譯方法標籤(bytecomp/translclass.ml),但不會暴露於輸入語言。我認爲區別是因爲字符串是可變的,所以共享用戶可見的字符串是可觀察的並且改變了程序的行爲,但是字符串常量已經被lambda解除,因此用戶可以觀察到語義上不一致的共享。用戶可見的字符串可能仍然會作爲兼容性中斷被拒絕。)

看看這些直接字符串由常量發送代碼處理的方式(asmcomp/cmmgen.ml:emit_constant),它們表示爲像通常的字符串,所以也許你可以修補編譯器在assert_failed中使用immstring,事情就會起作用。

[編輯由OP]

更改Const_base (Const_string fname)Const_immstring fname,同時輕微不相容,允許OCaml的編譯本身,編譯郵資-C和新的郵資-C通過其迴歸測試。在原來的例子,效果如下,而這正是所期望的結果:

$ 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 
+0

我知道這不是那麼禮儀發表評論時,你可以簡單地接受了答案,但我想對你表示祝賀解決方案。做得好。 – 2012-04-04 14:59:31

+0

好吧,謝謝:)一旦你提交了關於[bugtracker](http://caml.inria.fr/mantis/)的更改提議,這可能看起來不太令人滿意,而實際上知道這些東西的人會告訴你如何這個想法不好。 – gasche 2012-04-04 15:41:38

+0

我寧願保留任何一點點注意力,我仍然可以在uglinesses的問題跟蹤器上召喚我,但我沒有解決方案,但隨時可以在5573上進行思考。如果我找到了解決方案,那麼我將爲此提交解決方案一個作爲一個值得審查的補丁。 – 2012-04-04 18:37:29