Pytanie Poprawienie kodu lambda OCaml generuje dla asercji


Chciałbym ulepszyć kod lambda wygenerowany dla konstrukcji "asert" OCaml 3.12.1. Oto przykład:

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

Plik longfilename.ml powyżej jest reprezentatywny dla dużych modułów OCaml, dla których chciałbym ulepszyć generowanie kodu lambda. Kompiluje się do:

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

Powyższe jest strasznie niepotrzebne. Nazwa pliku źródłowego, z którego każde potwierdzenie może pochodzić, jest duplikowana. Winowajcą wydaje się być bytompomp / 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)]))])])
;;

Na pierwszy rzut oka wydaje się, że wystarczy podać nazwę Const_base(Const_string fname)i do przechowywania i ponownego użycia tabeli mieszania w czasie kompilacji. Do optymalizacji wewnątrz modułów, zmiany mogą być łatwe do opanowania (tak długo, jak tabela mieszająca jest resetowana w każdej jednostce kompilacji).

Jestem tu trochę poza moją głębią, zwłaszcza "reset w każdej kompilacji jednostka "część. Jakaś wskazówka?


10
2018-04-04 09:36


pochodzenie




Odpowiedzi:


Istnieje już mechanizm w kompilatorze OCaml, który udostępnia pewne stałe: patrz asmcomp/compilenv.ml i jego wykorzystanie, w szczególności structured_constants wartość, w asmcomp/cmmgen.ml. Nie znam tego kodu, więc nie jestem pewien, dlaczego twój konkretny przypadek użycia nie jest udostępniony, ale wydaje się, że istnieje różnica między kodem lambda, Const_base (Const_string foo) i Const_immstring foo; te późniejsze są wspólne, a może te pierwsze nie są.

Nie wiem, do czego służy przeznaczona semantyka immstring. Wydaje się, że kompilator używa go wewnętrznie do kompilowania etykiet metod (bytecomp/translclass.ml), ale nie jest wystawiony na język wprowadzania.

(Podejrzewam, że rozróżnienie jest takie, że łańcuchy są zmienne, więc udostępnianie łańcuchów widocznych dla użytkownika byłoby obserwowalne i zmieniałoby zachowanie programów, ale stałe łańcuchowe są już zniesione przez lambdę, dzięki czemu użytkownicy mogą już obserwować semantyczne niespójne współdzielenie. prawdopodobnie nadal byłaby odrzucana jako przerwa zgodności).

Patrząc na sposób, w jaki te bezpośrednie ciągi są obsługiwane przez stały kod emitujący (asmcomp/cmmgen.ml:emit_constant), są one reprezentowane jak zwykłe łańcuchy, więc może po prostu poprawisz kompilator, aby użyć an immstring w assert_failed i wszystko by działało.

[EDIT BY OP]

Wymiana pieniędzy Const_base (Const_string fname) w Const_immstring fname, chociaż nieznacznie niekompatybilny, pozwala OCamlowi kompilować się, kompilować Framę-C, a nowa Frama-C przechodzi testy regresji. W oryginalnym przykładzie efekt wygląda następująco, co było dokładnie pożądanym rezultatem:

$ 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

8
2018-04-04 12:27



Wiem, że napisanie komentarza nie jest tak proste, kiedy możesz po prostu zaakceptować odpowiedź, ale chciałem pogratulować ci rozwiązania, które zaoferowałeś. Dobra robota. - Pascal Cuoq
Cóż, dziękuję :) Może to wyglądać mniej satysfakcjonująco, gdy już złożysz propozycję zmian na stronie bugtracker, a ludzie, którzy faktycznie znają te rzeczy, mówią, jak zły był ten pomysł. - gasche
Wolałbym skupić się na jak najmniejszej uwagi, którą wciąż mogę przywołać na tropie problemu dla firm, do których nie mam rozwiązania, ale nie przejmuj się, jeśli chodzi o 5573. Jeśli znajdę rozwiązanie dla tego, przedstawię twoje rozwiązanie dla tego jako łatka zasługująca na recenzję. - Pascal Cuoq