2012-04-04 8 views
10

Me gustaría mejorar el código lambda generado para el constructo "assert" OCaml 3.12.1. Aquí está un ejemplo:Mejorando el código lambda OCaml genera para las aserciones

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

El longfilename.ml archivo anterior es representativa de grandes módulos OCaml para que me gustaría generación lambda-código a ser mejorado. Se compila a:

$ 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 
... 

Lo anterior es terriblemente redundante. El nombre del archivo fuente de donde proviene cada afirmación está duplicado. El culpable parece ser 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)]))])]) 
;; 

En vista de ello, parece que sería suficiente para dar un nombre a Const_base(Const_string fname), y para almacenar y reutilizar con un de compilación tiempo hash-table. Para la optimización intramódulo, , los cambios pueden ser manejables (siempre que la tabla hash se restablezca en cada unidad de compilación).

Estoy un poco fuera de mi alcance aquí, especialmente la parte de "reinicio en cada compilación ". ¿Alguna pista?

Respuesta

8

Ya existe un mecanismo en el compilador OCaml para compartir algunas constantes: ver asmcomp/compilenv.ml y su uso, en particular, del valor structured_constants, en asmcomp/cmmgen.ml. No estoy familiarizado con este código, por lo que no estoy seguro de por qué su caso de uso particular no se comparte, pero parece que hay una diferencia entre, en el código lambda, Const_base (Const_string foo) y Const_immstring foo; los últimos son compartidos, y tal vez los primeros no.

No sé cuál es la semántica prevista para immstring. Parece que el compilador lo usa internamente para compilar etiquetas de método (bytecomp/translclass.ml), pero no está expuesto al idioma de entrada.

(Sospecho que la distinción se debe a que las cadenas son mutables, por lo que compartir cadenas visibles para el usuario sería observable y cambiar el comportamiento de los programas, pero las constantes de cadenas ya están eliminadas para que los usuarios ya puedan observar el intercambio semánticamente inconsistente. las cadenas visibles para el usuario probablemente todavía se rechazarán como un rompimiento de compatibilidad.)

Mirando la forma en que las cadenas inmediatas son manejadas por el código de emisión constante (asmcomp/cmmgen.ml:emit_constant), se representan como las cadenas habituales, por lo que podría simplemente parche el compilador para usar un immstring en assert_failed y las cosas funcionarían.

[EDIT por la OP]

Cambio de Const_base (Const_string fname) en Const_immstring fname, mientras ligeramente incompatible, permite OCaml para compilar sí mismo, para compilar Frama-C y el nuevo Frama-C pasa sus pruebas de regresión. En el ejemplo original, el efecto es el siguiente, que era exactamente el resultado deseado:

$ 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

Yo sé que no es tan etiqueta para publicar un comentario cuando se puede simplemente aceptar la respuesta, pero quería felicitarle por la solución que ofreciste Bien hecho. –

+0

Bueno, gracias :) Esto puede parecer menos satisfactorio una vez que haya enviado una propuesta de cambio en [bugtracker] (http://caml.inria.fr/mantis/), y las personas que realmente saben esto le dicen cómo mala fue la idea. – gasche

+0

Prefiero reservar toda la atención que aún pueda invocar sobre el rastreador de problemas para las fechorías a las que no tengo la solución, pero no dude en opinar sobre 5573. Si encuentro una solución para eso, enviaré su solución para este uno como un parche merecedor de revisión. –