Skip to content

Commit

Permalink
reml binary (#136)
Browse files Browse the repository at this point in the history
* reml binary and cleanup
  • Loading branch information
melsman authored Oct 10, 2023
1 parent 0e3397f commit 012f4f6
Show file tree
Hide file tree
Showing 44 changed files with 1,441 additions and 702 deletions.
59 changes: 50 additions & 9 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# "build-test-deploy". It is triggered on push or pull request events
# on the master branch. It is also triggered when a tag is pushed, in
# which case a binary distribution is deployed. The build matrix is
# currently setup to run only with mlton as the primary SML compiler.
# currently setup to run only with mlkit as the primary SML compiler.

name: CI

Expand All @@ -28,8 +28,9 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04, macos-latest]
# mlcomp: [mlkit, mlton]
mlcomp: [mlton]
mlcomp: [mlkit, mlton]
# mlcomp: [mlton]
# mlcomp: [mlkit]

runs-on: ${{ matrix.os }}

Expand All @@ -43,31 +44,70 @@ jobs:
echo "RUNHOME=$(echo $HOME)" >> $GITHUB_ENV
- name: Install dependencies (linux)
if: ${{ env.OS == 'linux' }}
run: |
# sudo apt-get -qq update
sudo apt-get install -y gcc autoconf make
- name: Install dependencies (linux, mlton)
if: ${{ env.OS == 'linux' && matrix.mlcomp == 'mlton' }}
run: |
# sudo apt-get -qq update
sudo apt-get install -y gcc mlton autoconf make
sudo apt-get install -y mlton
- name: Install dependencies (macos)
if: ${{ env.OS == 'darwin' && matrix.mlcomp == 'mlton' }}
if: ${{ env.OS == 'darwin' }}
run: |
brew install gcc autoconf make
# The brew version of MLton has a bug
brew install mlton --HEAD
brew tap homebrew/cask
brew install --cask phantomjs
- name: Check
- name: Install dependencies (macos, mlton)
if: ${{ env.OS == 'darwin' && matrix.mlcomp == 'mlton' }}
run: |
# The brew version of MLton has a bug
brew install mlton --HEAD
- name: Install MLKit and smlpkg
working-directory: ${{ env.RUNHOME }}
run: |
echo "[OS: $OS, HOME: $RUNHOME]"
wget https://github.com/diku-dk/smlpkg/releases/download/v0.1.4/smlpkg-bin-dist-${{env.OS}}.tgz
tar xzf smlpkg-bin-dist-${{env.OS}}.tgz
echo "$HOME/smlpkg-bin-dist-${{env.OS}}/bin" >> $GITHUB_PATH
wget https://github.com/melsman/mlkit/releases/download/v4.7.4/mlkit-bin-dist-${{env.OS}}.tgz
tar xzf mlkit-bin-dist-${{env.OS}}.tgz
echo "$HOME/mlkit-bin-dist-${{env.OS}}/bin" >> $GITHUB_PATH
mkdir -p .mlkit
echo "SML_LIB $HOME/mlkit-bin-dist-${{env.OS}}/lib/mlkit" > .mlkit/mlb-path-map
- name: Check MLton
if: ${{ matrix.mlcomp == 'mlton' }}
run: |
mlton
echo 'github.event_name: ' ${{ github.event_name }}
echo 'github.ref: ' ${{ github.ref }}
- name: Configure
- name: Check MLKit
if: ${{ matrix.mlcomp == 'mlkit' }}
run: |
mlkit --version
smlpkg --version
echo 'github.event_name: ' ${{ github.event_name }}
echo 'github.ref: ' ${{ github.ref }}
- name: Configure With MLton
if: ${{ matrix.mlcomp == 'mlton' }}
run: |
./autobuild
./configure
- name: Configure With MLKit
if: ${{ matrix.mlcomp == 'mlkit' }}
run: |
./autobuild
./configure --with-compiler=mlkit
- name: Build MLKit
run: |
make mlkit
Expand All @@ -87,6 +127,7 @@ jobs:
make -C test/parallelism all
- name: Configure SmlToJs
if: ${{ matrix.mlcomp == 'mlton' }}
run: |
./configure --with-compiler="SML_LIB=`pwd` `pwd`/bin/mlkit"
Expand Down
6 changes: 6 additions & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ CLEAN=rm -rf MLB *~ .\#*
mlkit:
$(MKDIR) bin
$(MAKE) -C src mlkit
$(MAKE) -C src reml
$(MAKE) man_mlkit

.PHONY: smltojs
Expand All @@ -56,6 +57,7 @@ all: mlkit mlkit_basislibs smltojs smltojs_basislibs
.PHONY: mlkit_basislibs
mlkit_basislibs: mlkit
(cd basis && SML_LIB=.. ../bin/mlkit -c -no_gc basis.mlb)
(cd basis && SML_LIB=.. ../bin/mlkit -c -no_gc -par basis.mlb)
(cd basis && SML_LIB=.. ../bin/mlkit -c -gc basis.mlb)
(cd basis && SML_LIB=.. ../bin/mlkit -c -gc -prof basis.mlb)
(cd basis && SML_LIB=.. ../bin/mlkit -c -no_gc -prof -Pcee -Prfg -Ppp -print_rho_types -log_to_file basis.mlb)
Expand Down Expand Up @@ -197,6 +199,7 @@ install0:
$(MKDIR) $(INSTDIR)
$(MKDIR) $(BINDIR)
$(INSTALL) bin/mlkit $(BINDIR)
$(INSTALL) bin/reml $(BINDIR)
$(INSTALL) bin/mlkit-mllex $(BINDIR)
$(INSTALL) bin/mlkit-mlyacc $(BINDIR)
$(INSTALL) bin/rp2ps $(BINDIR)
Expand All @@ -209,6 +212,7 @@ install0:
$(MKDIR) $(MANDIR)
$(MKDIR) $(MANDIR)/man1
$(INSTALLDATA) man/man1/mlkit.1 $(MANDIR)/man1
$(INSTALLDATA) man/man1/reml.1 $(MANDIR)/man1
$(INSTALLDATA) man/man1/mlkit-mllex.1 $(MANDIR)/man1
$(INSTALLDATA) man/man1/mlkit-mlyacc.1 $(MANDIR)/man1
$(INSTALLDATA) man/man1/rp2ps.1 $(MANDIR)/man1
Expand Down Expand Up @@ -348,6 +352,7 @@ bootstrap:
man_mlkit:
$(MKDIR) man/man1
SML_LIB=$(exec_prefix)/lib/mlkit bin/mlkit -man > man/man1/mlkit.1
SML_LIB=$(exec_prefix)/lib/reml bin/reml -man > man/man1/reml.1

.PHONY: man_smltojs
man_smltojs:
Expand Down Expand Up @@ -443,6 +448,7 @@ smltojs_x64_tgz:
# $ ./autobuild
# $ ./configure
# $ make mlkit
# $ make reml
# $ make mlkit_libs
# $ make smltojs
# $ make smltojs_basislibs
Expand Down
78 changes: 78 additions & 0 deletions basis/ForkJoin-reml.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
structure ForkJoin :> FORK_JOIN = struct

fun alloc (n:int) (v:'a) : 'a array =
prim ("word_table0", n)

local

fun alloc_unsafe (n:int) : 'a array =
prim ("word_table0", n)

structure T = Thread

fun for (lo,hi) (f:int->unit) : unit =
let fun loop i =
if i >= hi then ()
else (f i; loop (i+1))
in loop lo
end
in
fun parfor `e (X:int) (lo:int,hi:int) (f: int #e -> unit) : unit while noput e =
if lo >= hi then ()
else let val m = lo+X
in if m >= hi (* last bucket *)
then for (lo,hi) f
else T.spawn (fn () => for (lo,m) f)
(fn _ => parfor X (m,hi) f)
end

fun pmap `[e] (f:'a #e ->'b) : ('a list -> 'b list) while noput e =
fn (xs:'a list) =>
let val v = Vector.fromList xs
val sz = Vector.length v
val a : 'b Array.array = alloc_unsafe sz
in parfor 1000 (0,sz) (fn i => Array.update(a,i,f(Vector.sub(v,i))))
; Array.foldr (op ::) nil a
end

fun par `[e1 e2] (f: unit #e1 -> 'a, g: unit #e2 -> 'b) : 'a * 'b while e1 ## e2 =
let val a1 : 'a array = alloc_unsafe 1
val b1 : 'b array = alloc_unsafe 1
in T.spawn (fn () => Array.update(b1,0,g())) (fn _ => (Array.update(a1,0,f())))
; (Array.sub(a1,0), Array.sub(b1,0))
end

fun pair `[e1 e2] (f: 'a #e1 -> 'b, g: 'c #e2 -> 'd) (x:'a,y:'c) : 'b * 'd while e1 ## e2 =
par (fn () => f x, fn () => g y)

type gcs = int * int (* max parallelism, min sequential work *)

val rec parfor'__noinline `[e] : (int*int #e-> unit) -> gcs -> int*int -> unit while noput e =
fn doit => fn (P,G) => fn (lo,hi) =>
if hi-lo <= 0 then () else
let val n = hi-lo
val m = Int.min(P+1, 1 + (n-1) div G) (* blocks *)
val k = n div m (* block size *)
val v = Vector.tabulate(m, fn i =>
let val first = i*k
val next = first+k
in (first,
if next > hi then hi else next)
end)
fun loop n =
if n >= m-1 then doit (Vector.sub(v,n))
else T.spawn (fn () => doit (Vector.sub(v,n)))
(fn _ => loop (n+1))
in loop 0
end

val rec parfor' `[e] : gcs -> int*int -> (int #e -> unit) -> unit while noput e =
fn gcs => fn (lo,hi) => fn f =>
let fun doit (lo,hi) = for (lo,hi) f
in parfor'__noinline doit gcs (lo,hi)
end

val parfor' = parfor'

end
end
56 changes: 56 additions & 0 deletions basis/Thread-reml.sml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
structure Thread :> THREAD = struct
type thread = foreignptr
type 'a t0 = ((unit->'a) * thread) ref
fun get__noinline ((ref (f,t0)): 'a t0) : 'a = prim("thread_get", t0)
fun spawn__noinline `[e1 e2] (f: unit #e1 -> 'a) (k: 'a t0 #e2 -> 'b) : 'b while e1 ## e2 =
let val rf : (unit -> 'a) ref = ref f
val fp_f : foreignptr = prim("pointer", !rf)

(* From a region inference perspective, coercing the type of
* a function to a pointer type is very unsafe, as the
* pointer type contains no information about which regions
* need to be kept alive for the pointer value to be
* valid. By including the type of the function in the type
* of the thread value, however, we keep all necessary
* regions alive.
*
* Moreover, we encapsulate the function in a ref to avoid
* that the closure is inlined into the "pointer" prim
* argument. If it is inlined, the closure will be allocated
* in a local stack-allocated region inside the "pointer"
* prim value, which cause the program to segfault.. *)

val t0 : thread = prim("spawnone", fp_f)
val t: 'a t0 = ref (f,t0)

fun force () =
if !(ref true) (* make sure the thread has terminated before returning *)
then get__noinline t (* and mimic that, from a type perspective, spawn has *)
else !rf() (* the effect of calling f *)

val res = k t handle e => (force(); raise e)
val _ = force ()

(* Notice that it is not safe to call `thread_free t0` here
* as t0 may be live through later calls to `get t`.
*
* What is needed is for the ThreadInfo structs to be region
* allocated and to add finalisers (thread_free) to objects
* in these regions. Technically, the thread is detached
* already in the thread_get function. However, the mutex
* and the ThreadInfo struct is kept live.
*)
in res
end

type 'a t = 'a t0

fun spawn `[e1 e2] (f: unit #e1 ->'a) (k: 'a t #e2 -> 'b) : 'b while e1 ## e2 =
spawn__noinline f k

fun get (x:'a t) : 'a =
get__noinline x

fun numCores () : int =
prim("numCores",())
end
10 changes: 10 additions & 0 deletions basis/par-reml.mlb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
local
basis.mlb
in
THREAD.sig
ThreadSeq.sml
Thread-reml.sml
FORK_JOIN.sig
ForkJoinSeq.sml
ForkJoin-reml.sml
end
1 change: 1 addition & 0 deletions man/man1/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ mlkit-mllex.1
mlkit-mlyacc.1
smltojs.1
mlkit.1
reml.1
rp2ps.1
1 change: 1 addition & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Makefile
Version.sml
config.h
mlkit
reml
smltojs
smlserverc
MLB
Expand Down
31 changes: 27 additions & 4 deletions src/Common/FLAGS.sig
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,31 @@ signature FLAGS =
item: 'a ref,
desc: string}

type baentry = {long: string, (* long option for use with mlkit command
* using `--', script files, and internally
* in the mlkit to lookup the current setting
* during execution. *)
short: string option, (* short option used in commands with - *)
menu: string list, (* entry::path; nil means no-show*)
item: bool ref, (* the actual flag *)
on: unit->unit, (* function to apply to turn entry on *)
off: unit->unit, (* function to apply to turn entry off;
* a toggling function can be made from
* these two and the item. *)
desc: string} (* description string; format manually
* with new-lines *)


(* Functions to add entries dynamically; remember to add a description
* telling what the flag is used for. If a nil-menu is given, the
* entry is not shown in help and the option cannot be given at the
* command line. *)

val add_bool_entry : bentry -> (unit -> bool)
val add_string_entry : string entry -> (unit -> string)
val add_stringlist_entry : string list entry -> (unit -> string list)
val add_int_entry : int entry -> (unit -> int)
val add_bool_entry : bentry -> (unit -> bool)
val add_string_entry : string entry -> (unit -> string)
val add_stringlist_entry : string list entry -> (unit -> string list)
val add_int_entry : int entry -> (unit -> int)
val add_bool_action_entry : baentry -> (unit -> bool)

(* Read and interpret option list by looking in directory and
* the extra nullary list and unary list *)
Expand All @@ -127,6 +143,13 @@ signature FLAGS =

val getOptions : unit -> options list

(* Blocked entries are flag entries that do not show up in help
information and that cannot be altered by commandline. Blocking an
entry makes it possible to specialize man-pages and --help info for
ReML and SMLtoJs. It also guards against mis-configurations and some
non-supported combination of flags. *)
val block_entry : string -> unit

structure Statistics :
sig
val no_dangling_pointers_changes : int ref
Expand Down
Loading

0 comments on commit 012f4f6

Please sign in to comment.