
Towards a native toplevel for the OCaml language Marcell Fischbach Benedikt Meurer∗ Compilerbau und Softwareanalyse Compilerbau und Softwareanalyse Fakult¨atIV, Universit¨atSiegen Fakult¨atIV, Universit¨atSiegen D-57068 Siegen, Germany D-57068 Siegen, Germany [email protected] [email protected] Abstract is currently only applicable to static program com- pilation. For example, it cannot yet be used with This paper presents the current state of our work multi-stage programming in MetaOCaml [34, 35], on an interactive toplevel for the OCaml language or the interactive toplevel ocaml. based on the optimizing native code compiler and This paper presents our work1 on a new native runtime. Our native toplevel is up to 100 times OCaml toplevel, called ocamlnat, which is based faster than the default OCaml toplevel, which is on the native runtime, the compilation engine of based on the byte code compiler and interpreter. the optimizing native code compiler and an earlier It uses Just-In-Time techniques to compile toplevel prototype implementation of a native toplevel by phrases to native code at runtime, and currently Alain Frisch. Our implementation currently sup- works with various Unix-like systems running on ports x86 and x86-64 processors [1, 10] and should x86 or x86-64 processors. work with any POSIX compliant operating system supported by the OCaml native code compiler. It is verified to work with Mac OS X 10.6 and 10.7, 1 Introduction Debian GNU/Linux 6.0 and above, and CentOS 5.6 and 5.7. The full source code is available from the The OCaml [17, 32] system is the main implemen- ocamljit-nat branch of the ocaml-experimental tation of the Caml language [6], featuring a pow- Git repository hosted on GitHub at [28]. erful module system combined with a full-fledged The paper is organized as follows: Section 2 object-oriented layer. It ships with an optimiz- motivates the need for a usable native OCaml ing native code compiler ocamlopt, for high per- toplevel. Section 3 presents an overview of the formance; a byte code compiler ocamlc and inter- OCaml compilers and Section 4 describes the pre- preter ocamlrun, for increased portability; and an vious ocamlnat prototype which inspired our work, interactive top-level ocaml based on the byte code while Section 5 presents our work on ocamlnat. compiler and runtime, for interactive use of OCaml Performance measures are given in Section 6. Sec- through a read-eval-print loop. tions 7 and 8 conclude with possible directions for further work. arXiv:1110.1029v2 [cs.PL] 27 Oct 2011 ocamlc and ocaml translate the source code into a sequence of byte code instructions for the OCaml virtual machine ocamlrun, which is based on the ZINC machine [16] originally developed for Caml 2 Motivation Light [18]. The optimizing native code compiler Interactive toplevels are quite popular among dy- ocamlopt produces fast machine code for the sup- namic and scripting languages like Perl, Python, ported targets (at the time of this writing, these Ruby and Shell, but also with functional program- are Alpha, ARM, Itanum, Motorola 68k, MIPS, ming languages like OCaml, Haskell and LISP. In PA-RISC, PowerPC, Sparc, and x86/x86-64), but 1The initial work in this area was done as part of the first ∗Corresponding Author author's diploma thesis. 1 case of scripting languages the interactive toplevel cleaner and simpler way. is usually the only frontend to the underlying in- terpreter or Just-In-Time compiler. Native runtime There are scenarios where only In case of OCaml, the interactive toplevel is only the native code runtime is available and hence the one possible interface to the byte code interpreter; byte code toplevel, which depends on the byte code it is also possible to separately compile source files runtime, cannot be used. One recent example here to byte or native code object files, link them into is the Mirage cloud operating system [21, 22, 23], libraries or executables, and deploy these libraries which compiles OCaml programs to Xen micro- or executables. The OCaml toplevel is therefore kernels [4] and executes them via the Xen hyper- mostly used for interactive development, rapid pro- visor [38]. Mirage uses the OCaml toplevel as OS totyping, teaching and learning, as an interactive console, but is currently limited to the byte code program console or for scripting purposes. toplevel in read-only mode, due to the lack of a The byte code runtime is the obvious candidate toplevel that works with the native code runtime. to drive the interactive toplevel, because the plat- form independent byte code is very portable and easy to generate { compared to native machine 3 Overview of the OCaml code. And in fact the byte code toplevel has served compilers users and developers well during the last years. But nevertheless there are valid reasons to have a native In this section we briefly describe the OCaml com- code toplevel instead of or in addition to the byte pilers, covering both the byte code compiler ocamlc code toplevel: and the optimizing native code compiler ocamlopt. Feel free to skip to section 4 if you are already fa- miliar with the details. Performance This is probably the main reason why one wants to have a native code toplevel. While the performance of the byte code interpreter is acceptable in many cases (which can be improved source program by using one of the available Just-In-Time compil- Parsing ers [27, 26, 29, 33]), it is not always sufficient to handle the necessary computations. Sometimes one Parsetree needs the execution speed of the native runtime, Typing which can be up to hundred times faster than the byte code runtime as we will show in Section 6. Typedtree For example, the Mancoosi project [24] has de- Translate veloped a library that allows to perform analysis of large sets of packages in free software distribu- Lambda tions, that can be done acceptably efficiently with Simplify the native code compiler and runtime, but are too slow in bytecode. To perform interactive analy- sis (i.e. select packages with particular properties, Bytegen Asmgen analyse them, . ), having a native toplevel is re- ally the only way to go for them, as it can combine byte code native code the flexibility of the toplevel interaction with the speed of native code. Tools such as ocamlscript [25] try to combine the performance of the code generated by the optimiz- Figure 1: The OCaml compilers ing native code compiler with the flexibility of a \scripting language interface". But this is basically Figure 1 gives an overview of the compiler phases just a work-around { with several limitations. A and representations in the OCaml byte and na- native toplevel would address this issue in a much tive code compilers. Compilation always starts 2 by parsing an OCaml source program (either from files asmcomp/cmm.mli and asmcomp/cmmgen.ml). a source file or a source region in interactive mode) into an abstract syntax tree (AST, see file parsing/parsetree.mli of the OCaml source code). Compilation then proceeds by computing Lambda the type annotations to produce a typed syntax tree (see file typing/typedtree.mli). Closure conversion From this typed syntax tree, the compiler gen- Clambda erates a so called lambda representation (see file bytecomp/lambda.mli) inspired by the untyped C-- generation call-by-value λ-calculus [3, 11, 30]. This lambda Cmm representation is then optimized by transforming lambda trees into better or smaller lambda trees Instruction selection (see file bytecomp/simplif.ml), yielding a final Mach platform independent, internal representation of the source program as result of the compiler fron- Alloc combining tend phases. Mach The simplified lambda representation is then used as input for the respective compiler backend, Register allocation which is either Mach • the Bytegen module in case of the byte code Linearization compiler (see file bytecomp/bytegen.ml), or Linearize • the Asmgen module in case of the op- timizing native code compiler (see file Instruction scheduling asmcomp/asmgen.ml). native code The byte code backend, which is used by the byte code compiler ocamlc as well as the byte code toplevel ocaml, basically transforms the simpli- fied lambda representation into an equivalent byte Figure 2: Native code generation (Asmgen module) code program (see file bytecomp/instruct.mli), suitable for (a) direct execution by the byte code Afterwards the Instruction selection phase (see interpreter ocamlrun or (b) just-in-time compila- file asmcomp/selection.ml) picks appropriate in- tion using either OCAMLJIT [33] or OCamlJIT2 structions for the target machine, transforming the [26, 27, 29]. This is done by the Emitcode module C-- code into a tree based representation of the (see file bytecomp/emitcode.ml). Additional de- machine code (see file asmcomp/mach.mli). The tails about the byte code compiler and runtime can next step attempts to combine multiple heap al- be found in [16], [27] and [33]. locations within a basic block into a single heap The native code backend, which is used by allocation (see file asmcomp/comballoc.ml), prior the optimizing native code compiler ocamlopt as to allocating and assigning physical registers to well as the native toplevel ocamlnat, is shown in the virtual registers used in the machine code (see Figure 2. It takes the simplified lambda repre- function regalloc in file asmcomp/asmgen.ml). sentation as input and starts by transforming it The final phases linearize the machine code (see into a variant of the lambda representation (see file asmcomp/linearize.ml) and perform instruc- file asmcomp/clambda.mli) with explicit closures tion scheduling for better performance (see file and explicit direct/indirect function calls (see file asmcomp/scheduling.ml), yielding the final rep- asmcomp/closure.ml).
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages10 Page
-
File Size-