Poly/ML Version 5
New Features
- Support for stand-alone binaries
- Support for additional platforms:
AMD64, Intel Macs, Cygwin
- No artificial limits on size
of heaps or saved image
- Uses standard GNU tools for building
- Fixed address mmap and trap-handling
removed
Version 5
Thanks to some financial support
from the Verisoft project organised through the Technical University of Munich
I have spent several months updating the Poly/ML run-time system. There are
many internal changes detailed below but there is one major change that is likely
to affect all users. The persistent storage system that has been a feature of
Poly/ML almost since the beginning has finally reached its sell-by date and
has been removed. In its place there is the facility to export ML functions
as object files and link them to produce stand-alone executables.
Although the ML code has not been
significantly changed, with the exception of a new code-generator for the 64-bit
AMD/Intel processor, the run-time system has been modified substantially. The
aim has been to try to produce a version that will work across a wider range
of systems than before and will be much simpler to maintain. The C code has
been converted to C++ and standard GNU tools: autoconf, automake and libtool
are used to build the system. Memory mapping to fixed addresses, which caused
problems with various Linux distributions, has been removed and the use of traps
to handle arbitrary precision overflow and heap limits has been replaced by
calls into the run-time system. The artificial limits on the size of the heap
and of the saved database have been removed and the only limit on the size of
the working heap is likely to be swap space.
To build and install Poly/ML download
and unpack the source. You can then build poly with the commands
./configure
make
make install
./configure by default places installed
files within /usr/local and in particular the libraries are placed in /usr/local/lib.
Some Unix distributions (e.g. Fedora Core) do not include /usr/local/lib in
the library search path and on those distributions it may be better to override
this by specifying
./configure --prefix=/usr
You build an application by constructing
your application as an ML function and calling PolyML.export.
PolyML.export takes as its argument
a file name for the resulting object file and a function to export. It will
automatically add the normal extension for an object file (.o or .obj as appropriate)
unless it already included and write out the function and any data reachable
from it as a normal operating system object file. This can then be linked with
the poly libraries to build an application.
Example of building an application
$ poly
Poly/ML 5.0 Release
> fun f () = print "Hello World\n";
val f = fn : unit -> unit
> PolyML.export("hello", f);
val it = () : unit
> ^D
$ cc -o hello hello.o -lpolymain -lpolyml
$ ./hello
Hello World
If you have installed the libraries
in a directory that is not in the search path you may need to add this. For
example
cc -o hello hello.o -L /usr/local/lib
-lpolymain -lpolyml
It is possible to use the ld command rather than cc here but you may need
to include some of the default C and C++ libraries on the command line.
On some platforms it may be necessary to add -lstdc++.
It is often the case that applications
built using Poly/ML will want to use the normal Poly/ML top-level but with additional
ML functions or structures built in. In the old version this was achieved by
compiling the new declarations and then committing the database. The new version
does this slightly differently. First compile in the new declarations as before
and then export the Poly/ML top level by exporting PolyML.rootFunction.
$ poly
Poly/ML 5.0 Release
> val myValue = "This is a new value";
val myValue = "This is a new value" : string
> PolyML.export("mypoly", PolyML.rootFunction);
val it = () : unit
> ^D
$ cc -o mypoly mypoly.o -lpolymain -lpolyml
$ ./mypoly
Poly/ML 5.0 Beta1
> myValue;
val it = "This is a new value" : string
>
PolyML.export
writes its output to an object file in the native format on the machine on which
it is running. Currently Poly/ML supports three different formats: ELF, used
on Linux, FreeBSD and Solaris; PCOFF, used on Windows and Cygwin and Mach-O,
used on Mac OS X. If it is necessary to distribute software in object format
it would be inconvenient to have to produce versions for each combination of
architecture (e.g. X86-32, X86-64, PPC and Sparc) and each possible object format.
To avoid this there is a PolyML.exportPortable
function which takes similar arguments to PolyML.export
but writes its output to a text file in a portable format. There is a polyimport
command which loads a file stored in this format and runs it.
$ poly
Poly/ML 5.0 Release
> fun f () = print "Hello World\n";
val f = fn : unit -> unit
> PolyML.exportPortable("hello", f);
val it = () : unit
> ^D
$ polyimport hello.txt
Hello World
While this is convenient for porting
the portable format is not designed for efficiency. The Poly/ML build process
uses the portable format within the distribution but the build script then exports
the code in the native format. N.B. The portable format only avoids the need
to produce different object code formats. It is not portable across different
architectures (e.g. i386 to PPC) since the portable file still contains native
machine instructions encoded as strings.
The previous version of Poly/ML had
a command line option to compress a database by sharing immutable data. This
has been replaced in the new version by the PolyML.shareCommonData
function. This takes as its argument any data structure and it processes this
structure replacing any multiple occurrences of the same immutable data by a
pointer to a single occurrence. In effect, wherever in the data structure there
are two substructures which would be equal using the ML definition of equality
there will be a pointer to a single data structure.
The intended use of this is primarily
to reduce the size of a data structure before it is exported. It can be used
in the above example but in this case the function being exported is so simple
that it is unlikely to be worthwhile.
$ poly
Poly/ML 5.0 Release
> fun f () = print "Hello World\n";
val f = fn : unit -> unit
> PolyML.shareCommonData f;
val it = () : unit
> PolyML.export("hello", f);
val it = () : unit
> ^D
The new version uses the standard
GNU tools: autoconf, automake and libtool. There is no need to install these
tools in order to install and run Poly/ML unless you need to make modifications
to the setup which are not handled within the configure and make files. Using
these tools should make porting to other versions of Unix easier and should
make it fairly simple to build binary or source distributions to include in
Unix distributions.
The command line arguments to Poly/ML
have been simplified. There are a few command line arguments that are taken
by the Poly/ML run time system and the remainder are passed to the application
via the standard basis library CommandLine structure. The run-time system recognises
the following arguments:
| -H |
<Initial heap size (MB)> |
| --immutable |
<Initial size of immutable
buffer (MB)> |
| --mutable |
<Initial size of mutable
buffer(MB)> |
| --debug |
<Debug options> |
| --timeslice |
<Time slice (ms)> |
The poly application itself recognises
a few arguments:
| -v |
Print the version
of Poly/ML and exit |
| --help |
Print the list of arguments
and exit |
| -q |
Suppress the start-up message |
If you are building your own application
that recognises --help as a command line argument you should call PolyML.rtsArgumentHelp()
to retrieve the information about the run-time system arguments and include
this in any help text you produce.
The heap size arguments set the initial
heap size but the heap may grow beyond this if your application needs more space.
If no argument is set the default size is half the physical memory available
on your machine.
DCJM 2nd January 2007
|