manticoreproject / manticore Goto Github PK
View Code? Open in Web Editor NEWParallel ML compiler
Home Page: http://manticore.cs.uchicago.edu
License: MIT License
Parallel ML compiler
Home Page: http://manticore.cs.uchicago.edu
License: MIT License
From the old "curried vs uncurried" bug report, when compiling with -sequential
, which also turns on unboxing, we get the following broken BOM after unboxing
➤ ../../../bin/pmlc -sequential -Cbom.check-all=true curried_vs_uncurried.pml
***** Bogus BOM in Main after unbox *****
** type mismatch in Apply _t<BB80>#1.1 in h_uncurried<C6AA>#2.2
== expected int
== but found [int]
** type mismatch in Apply _t<BA8F>#1.1 in h_uncurried<C6AA>#2.2
== expected int
== but found [int]
broken BOM dumped to broken-BOM
bom/check-bom.sml:544.11-544.28: Fail: broken BOM
Here's the program:
fun theFunction x i =
let fun g x accum =
case x
of x::xs => h xs (accum + x)
| nil => accum
and h x accum =
case x
of y::nil => g x accum
| x::xs => h xs (accum + x)
| nil => accum
in g x 0 end
val _ = print("Result = " ^ Int.toString (theFunction (List.tabulate(100, fn _ => 1)) 1000 ) ^ "\n")
@kavon Hello! I am facing an issue with building manticore using Nix using SML/NJ v110.84
on x86_64. (Failing build log)
The error is being encountered with code in amd64-gen-fn.sml
[compiling driver/(x86_64-linux.cm):../codegen/(sources.cm):(wrapper.cm):(group.cm):amd64/amd64-gen-fn.sml]
codegen/amd64/amd64-gen-fn.sml:110.33-118.7 Error: value type in structure doesn't match signature spec
name: signBit
spec: int -> AMD64MLTree.rexp
actual: int -> Label.label
codegen/amd64/amd64-gen-fn.sml:110.33-118.7 Error: value type in structure doesn't match signature spec
name: negateSignBit
spec: int -> AMD64MLTree.rexp
actual: int -> Label.label
Error: Compiler bug: ModuleUtil: getStr: bad entity
Compilation failed.
make[2]: *** [Makefile:83: pmlc.x86-linux] Error 1
make[2]: Leaving directory '/nix/store/5zy5w8jjm8vzaqjhhqpn9z7mpncmk01m-manticore-2017.08.22/repo_checkout/src/tools/mc'
make[1]: *** [Makefile:39: build] Error 2
make[1]: Leaving directory '/nix/store/5zy5w8jjm8vzaqjhhqpn9z7mpncmk01m-manticore-2017.08.22/repo_checkout/src'
make: *** [Makefile:58: build] Error 2
builder for '/nix/store/g21hjshf6pha15fdqmg6k34id718gijn-manticore-2017.08.22.drv' failed with exit code 2
error: build of '/nix/store/g21hjshf6pha15fdqmg6k34id718gijn-manticore-2017.08.22.drv' failed
The same build succeeds with SML/NJ v110.79
. (Working build log) -
[compiling driver/(x86_64-linux.cm):../codegen/(sources.cm):(wrapper.cm):(group.cm):amd64/amd64-gen-fn.sml]
codegen/amd64/amd64-gen-fn.sml:102.23-104.30 Warning: match nonexhaustive
32 => ...
64 => ...
codegen/amd64/amd64-gen-fn.sml:87.17-89.24 Warning: match nonexhaustive
32 => ...
64 => ...
Any help on why this is failing would be greatly appreciated!
➤ ../bin/pmlc -sequential -mlrisc literal.pml
literal.s:2131:9: error: invalid escape sequence (unrecognized character) in '.asciz' directive
.asciz "mlrisc\'s string literal bug"
^
error compiling generated assembly code
from the following program
val _ = print "mlrisc's string literal bug"
On Ubuntu 18.04, likely using clang to compile.
See the comment in alt-ret-tuple.pml
from the regression suite for details. I'm not sure what's going on actually. Referenced in commit 9ad955a
Opening issue related to this bug, since the workaround below was removed from trunk:
(* MLRISC is incorrectly naming some of the 8-bit registers, so as a simple
* workaround, we are just going to find/replace them in the output text file
*)
fun replace8BitRegisters asmFile = let
val cmd = "sed -i \"s/%ah/%spl/g; s/%ch/%bpl/g; s/%dh/%sil/g; s/%bh/%dil/g\" " ^ asmFile
in
ignore (OS.Process.system cmd)
end
From the nucleic benchmark's TODO, there seems to be an issue with allocating a large list in the heap from a literal. I believe this is a problem regardless of what backend is used.
I think this program hits a segfault because it tries to allocate too much in
the local heap (aka, a lot of allocation within one function). In particular,
take a look at how huge the list literals are in this program.
In addition, it seems compiling this program can cause LLC to hang for a
very long time (over 2 minutes).
I see two solutions:
(1) Try adding a test to see how much allocation is checked for by
add-alloc-checks in CFG. If the value is too high, maybe we should split
the block or insert an additional heap test.
(2) [preferred] move the data stored in the list constant into a file, and
read it in line-by-line to build the list up.
See the TODO file in: https://github.com/ManticoreProject/benchmark/tree/master/benchmarks/programs/seq-nucleic
Before wrap-captures we have
fun contFib_uncurried<C6EA>#4.4 (unboxP<C6F5>#9:int,param<C6F6>#4.4:cont(any) / retK<C6F7>#0:cont(int),_exh<C6F8>#4:cont(any)) =
(* ... *)
cont currentContinuation<C717>#1 (ccArg<C718>#1:any) =
let c<C712>#1:[int] = ([int])ccArg<C718>#1
let _t<C713>#1:int = #0(c<C70B>#1)
let _t<C714>#1:int = #0(c<C712>#1)
let _t<C715>#1:int = I32Add(_t<C713>#1,_t<C714>#1)
let res<C716>#1:[int] = alloc (_t<C715>#1)
throw param<C6F6>#4.4 res<C716>#1
(**** End currentContinuation<C717>#1 ****)
apply contFib_uncurried<C6EA>#4.4 (_t<C70D>#1,currentContinuation<C717>#1 / letJoinK<C85D>#1,_exh<C6F8>#4)
Note that contFib_uncurried
does not return. We're currently generating the following wrapping
fun manipK2<C93C>#1 (currentContinuation<C939>#1:cont(any) / landingPadK<C93A>#1.1:cont(int,any),deadExnK<C93B>#0:cont(any)) =
cont invokeRetk<C93D>#0 (param<C93E>#1:any) =
let t<C93F>#1:int = 1:int
throw landingPadK<C93A>#1.1 (t<C93F>#1,param<C93E>#1)
(* ... *)
cont setjmpLandingPad<C933>#1 (regularRet<C934>#1:int,arg<C935>#2:any) =
let t<C938>#1:int = 0:int
if I32NEq(regularRet<C934>#1,t<C938>#1) then
let arg<C936>#1:int = (int)arg<C935>#2 (* invalid cast! *)
throw retK<C6F7>#2.2 arg<C936>#1 (* this return never will happen *)
else
let arg<C937>#1:any = (any)arg<C935>#2
throw currentContinuation<C717>#1.1 arg<C937>#1
callec (manipK2<C93C>#1 / setjmpLandingPad<C933>#1,deadExh<C941>#1)
Previously this was just a bit inefficient, but it's also incorrect since
an we don't know how to match up the types even if a return did occur (the
unboxing of the int).
It's better to just omit the landing pad in this case and just generate:
callec (manipK2<C93C>#1 / currentContinuation<C717>#1,deadExh<C941>#1)
so that C717
turns into a return cont, instead of a join cont.
When I write a parallel sorting program, I found that the following code causes segmentation fault both on my mac and linux.
fun copy a b e d j =
if e < b then ()
else let val v = Array.sub (Array.sub (a, 0), b)
in Array.update (Array.sub (d, 0), j, v);
copy a (b+1) e d (j+1)
end
fun sort a b e =
if e <= b then () else
let val q = Int.quot (b + e, 2)
in sort a b q;
sort a (q+1) e;
copy a b e a b
end
val a = Array.array (1, Array.array (1024, 0))
val _ = sort a 0 1023
I checked out the repository and compiled the compiler as follows:
git clone https://github.com/ManticoreProject/manticore.git
git checkout 757fbcc4d # to make clear which revision I used
autoconf -Iconfig
autoheader -Iconfig
./configure --prefix=$PWD/dest
mkdir -p dest/bin dest/lib
make install
I saved the above code in bug.pml and executed it as follows:
$ dest/bin/pmlc -o bug bug.pml
$ ./bug
Segmentation fault
The new seq-deriv
benchmark program crashes Manticore with:
➤ ../../../../../bin/pmlc -sequential mc-seq.mlb
../../smlnj-lib/Util/hash-table-fn.sml:85.31-85.40: Fail: UncurriedFns
This failure is raised from the uncurrying pass in BOM. Here's the program:
(* adapted from the Larceny benchmark
;;; DERIV -- Symbolic derivation.
;;; Returns the wrong answer for quotients.
;;; Fortunately these aren't used in the benchmark.
*)
datatype expr
= Add of expr list
| Sub of expr list
| Mul of expr list
| Div of expr list
| Num of int
| X
structure Benchmark = struct
val hd = List.hd
val tl = List.tl
val map = List.map
val app = List.app
val foldl = List.foldl
fun prnt p = (case p
of X => print "x"
| Num a => print (Int.toString a)
| Add xs => prntLst "+" xs
| Sub xs => prntLst "-" xs
| Mul xs => prntLst "*" xs
| Div xs => prntLst "/" xs
(* end case *))
and prntLst symb xs = (print "("; print symb;
app prnt xs; print ")\n")
fun equal p = (case p
of (X, X) => true
| (Num a, Num b) => a = b
| (Add xs, Add ys) => chkLists (xs, ys)
| (Sub xs, Sub ys) => chkLists (xs, ys)
| (Mul xs, Mul ys) => chkLists (xs, ys)
| (Div xs, Div ys) => chkLists (xs, ys)
| _ => false
(* end case *))
and chkLists p = ListPair.foldlEq chk true p
and chk (a, b, acc) = acc andalso equal (a, b)
fun deriv a = (case a
of X => Num 1
| Num _ => Num 0
| Add es => Add (map deriv es)
| Sub es => Sub (map deriv es)
| Mul es => Mul [
a,
Add (map (fn x => Div [deriv x, x]) es)
]
| Div (x :: y :: nil) => Sub [
Div [deriv x, y],
Div [x, Mul [y, y, deriv y]]
]
| _ => raise Fail "No derivation method available"
(* end case *))
fun go (ans, exp) = let
val computed = deriv exp
in
if equal (ans, computed)
then ()
else (prnt computed ; raise Fail "wrong answer!")
end
end
structure Main =
struct
val iterations = 2000000
fun main _ = let
fun mkExp a b =
Add [
Mul [Num 3, X, X],
Mul [a, X, X],
Mul [b, X],
Num 5
]
fun mkAns a b =
Add [
Mul [
Mul [Num 3, X, X],
Add [
Div [Num 0, Num 3],
Div [Num 1, X],
Div [Num 1, X]
]
],
Mul [
Mul [a, X, X],
Add [
Div [Num 0, a],
Div [Num 1, X],
Div [Num 1, X]
]
],
Mul [
Mul [b, X],
Add [
Div [Num 0, b],
Div [Num 1, X]
]
],
Num 0
]
val a = Num 5
val b = Num 7
val exp = mkExp a b
val ans = mkAns a b
fun doit () = Benchmark.go (ans, exp)
fun lp 0 = ()
| lp n = (doit(); lp (n-1))
fun start () = lp iterations
in
start ()
end
end
val _ = Main.main (CommandLine.name (), CommandLine.arguments ())
See the file here: https://smlnj-gitlab.cs.uchicago.edu/manticore/benchmarks/blob/704571634ff114d06cff9f7d87256eab627536a2/benchmarks/programs/seq-deriv/prog.pml
it seems that the alignment of stack slots setup by the prologue does not match the LLVM code generator's expectations. From the ffi-fib
benchmark on all stack-based variants:
Thread 2 "a.out" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff63ff700 (LWP 28269)]
go_cfg3CDE_49A0 () at mc-seq.s:732
732 movapd %xmm1, 40(%rsp) # 16-byte Spill
Seems there's a bug in case simplify? I'm using d5dfda2
➤ ../trunk-pmlc/bin/pmlc -Cbom.check-all=true fib-datatype.pml
***** Bogus BOM in Main after case-simplify *****
** invalid cast:(_t<D762>#2:int) = (int)left<F8FC>#5:any
** invalid cast:(_t<D773>#1:int) = (int)right<F8FD>#7:any
** type mismatch in return from fib<F8FA>#3.3
== expected any
== but found int
** type mismatch in return from fib<F8FA>#3.3
== expected any
== but found int
** invalid cast:(_t<D751>#1:int) = (int)right<F8FD>#7:any
** type mismatch in return from fib<F8FA>#3.3
== expected any
== but found int
** type mismatch in return from fib<F8FA>#3.3
== expected any
== but found int
** invalid cast:(_t<D78A>#1:int) = (int)ans<F90E>#3:any
broken BOM dumped to broken-BOM
bom/check-bom.sml:544.11-544.28: Fail: broken BOM
See fib-datatype.pml
below:
datatype fib_result
= Zero
| One
| Val of int
fun add a b = (case (a, b)
of (Zero, b) => b
| (a, Zero) => a
| (One, One) => Val 2
| (One, Val b) => Val (b+1)
| (Val a, One) => Val (a+1)
| (Val a, Val b) => Val (a+b)
(* end case *))
fun show a = (case a
of Zero => "0"
| One => "1"
| Val a => Int.toString a
(* end case *))
fun fib n = (case n
of 0 => Zero
| 1 => One
| _ => let
val left = fib (n-1)
val right = fib (n-2)
in
add left right
end
(* end case *))
val i2s = Int.toString
val n = 30 (* https://oeis.org/A000045/list *)
val ans = fib n
val _ = print ("fib(" ^ i2s n ^ ") = " ^ show ans ^ "\n")
smlnj 110.95 (probably 110.94 too, as it switched the type of source-file positions from Position.int
to Int.int
) can't build the latest revision of manticore:
[compiling driver/(x86_64-linux.cm):../codegen/(sources.cm):(wrapper.cm):(group.cm):../common/(sources.cm):error.sml]
common/error.sml:137.39-137.59 Error: operator and operand do not agree [tycon mismatch]
operator domain: (Int64.int * Int64.int) option *
(Int64.int * Int64.int) option
operand: span option * span option
in expression:
lt ((fn <pat> => <exp>) e1,(fn <pat> => <exp>) e2)
Compilation failed.
It works with the following change:
diff --git a/src/tools/mc/common/error.sml b/src/tools/mc/common/error.sml
index e880c5f18..370ce05eb 100644
--- a/src/tools/mc/common/error.sml
+++ b/src/tools/mc/common/error.sml
@@ -129,9 +129,9 @@ structure Error :> sig
fun lt (NONE, NONE) = false
| lt (NONE, _) = true
| lt (_, NONE) = false
- | lt (SOME(l1, r1), SOME(l2, r2)) = (case Position.compare(l1, l2)
+ | lt (SOME(l1, r1), SOME(l2, r2)) = (case Int.compare(l1, l2)
of LESS => true
- | EQUAL => (Position.compare(r1, r2) = LESS)
+ | EQUAL => (Int.compare(r1, r2) = LESS)
| GREATER => false
(* end case *))
fun cmp (e1 : error, e2 : error) = lt(#pos e1, #pos e2)
I'm not sure if it's the right approach as it would break compilation with smlnj versions before 110.94 (and I didn't see any pragmas/etc for backwards-compatibility of this sort; though I'm really new to SML and might've missed it).
What's your usual approach to this?
Greetings from Sweden and Chalmers University of Technology!
I may have found something when exploring parallel arrays in Manticore. Here is a piece of code that works perfectly fine:
fun f n = if n <= 0 then 0 else 1 + f (n - 1)
val xs = [ 1, 2, 3 ]
val _ = map f xs
Here is a similar program with a parallel array and PArray.map
instead of a list and the regular map
:
(* f same as before *)
val xs = PArray.fromRope (Rope.tabulateSequential (fn x => x) (1, 3))
val _ = PArray.map (fn x => f x) xs
That code also works. But watch what happens when I eta-reduce the mapped function:
val _ = PArray.map f xs
The code doesn't compile anymore:
$ pmlc eta.pml
***** Bogus CPS in Main after inline *****
** unbound variable f<11431>#4.4
** unbound variable f<11431>#4.4 in Apply
** unbound variable f<11431>#4.4
** unbound variable f<11431>#4.4 in Apply
broken CPS dumped to broken-CPS
The dumped file is 1.7 MB, but I can't really extract any useful information from it.
It also turns out that everything works fine if f
is not recursive:
fun f n = if n <= 0 then 0 else 1
val xs = PArray.fromRope (Rope.tabulateSequential (fn x => x) (1, 3))
val _ = PArray.map f xs
I'm not an expert, but there seems to be something going on here. What do you think?
The following benchmark program (seq-mazefun
) executes pretty quickly in MLton
, but after compiling with Manticore it has runaway memory usage. Of course this causes GC thrashing so the program doesn't seem to terminate before hitting the swapfile.
There must be some bug causing some data to stay live according to the GC longer than it should.
(* from the Larceny benchmark suite
;;; MAZEFUN -- Constructs a maze in a purely functional way,
;;; written by Marc Feeley.
;;; ported to SML by Kavon Farvardin
*)
datatype maze_elm
= Pt of int * int
| Empty
structure Benchmark = struct
val hd = List.hd
val tl = List.tl
val concat = List.concat
val length = List.length
val null = List.null
val foldr = List.foldr
fun tup1 (x, _) = x
fun tup2 (_, x) = x
(* operations on maze elms *)
fun fst e = (case e
of Pt (x, _) => x
| _ => raise Fail "not a point"
(* end case *))
fun snd e = (case e
of Pt (_, x) => x
| _ => raise Fail "not a point"
(* end case *))
fun mazeElmEqual p = (case p
of (Pt (x, y), Pt (a, b)) => x = a andalso y = b
| (Empty, Empty) => true
| _ => false
(* end case *))
fun mazeElmToString p = (case p
of Pt _ => " _"
| Empty => " *"
(* end case *))
fun printStringMat mat =
app (fn lst => (app print lst; print "\n")) mat
(***********)
(* the args to f are flipped,
i.e. acc is on the left in Scheme *)
fun foldl f id xs = let
fun lp (xs, acc) = (case xs
of nil => acc
| x :: xs => lp(xs, f (acc, x))
(* end case *))
in
lp (xs, id)
end
fun for lo hi f = let
fun lp lo =
if lo < hi
then f lo :: lp (lo + 1)
else nil
in
lp lo
end
fun listRead lst i =
if i = 0
then hd lst
else listRead (tl lst) (i-1)
fun listWrite lst i new =
if i = 0
then new :: tl lst
else hd lst :: listWrite (tl lst) (i-1) new
fun listRemovePos lst i =
if i = 0
then tl lst
else hd lst :: listRemovePos (tl lst) (i-1)
fun member x = List.exists (fn y => mazeElmEqual (x, y))
fun hasDuplicates lst = (case lst
of nil => false
| x :: xs => member x xs orelse hasDuplicates xs
(* end case *))
fun makeMatrix n m init =
for 0 n (fn i =>
for 0 m (fn j =>
init i j
)
)
fun matrixRead mat i j = listRead (listRead mat i) j
fun matrixWrite mat i j new =
listWrite mat i (listWrite (listRead mat i) j new)
fun matrixSize mat = (length mat, length (hd mat))
fun matrixMap f mat = map (fn lst => map f lst) mat
fun nextRandom cur =
((cur * 3581) + 12751) mod 131072
fun shuffle lst = let
fun shuf lst rand =
if null lst
then nil
else let
val newRand = nextRandom rand
val i = newRand mod (length lst)
in
listRead lst i
:: shuf (listRemovePos lst i) newRand
end
in
shuf lst 0 (* <- the seed *)
end
fun odd n = n mod 2 = 1
fun even n = n mod 2 = 0
fun caveToMaze cave = matrixMap mazeElmToString cave
fun pierce pos cave = matrixWrite cave (fst pos) (snd pos) pos
fun neighboringCavities pos cave = let
val size = matrixSize cave
val n = tup1 size
val m = tup2 size
val i = fst pos
val j = snd pos
fun notEmpty (i, j) = (case matrixRead cave i j
of Empty => false
| _ => true
(* end case *))
in
concat [
if i > 0 andalso notEmpty (i-1, j)
then [Pt (i-1, j)]
else nil,
if i < n-1 andalso notEmpty (i+1, j)
then [Pt (i+1, j)]
else nil,
if j > 0 andalso notEmpty (i, j-1)
then [Pt (i, j-1)]
else nil,
if j < m-1 andalso notEmpty (i, j+1)
then [Pt (i, j+1)]
else nil
]
end
and changeCavity cave pos newID = let
fun change cave pos newID oldID = let
val i = fst pos
val j = snd pos
val cavityID = matrixRead cave i j
in
if mazeElmEqual (cavityID, oldID)
then foldl (fn (c, nc) =>
change c nc newID oldID)
(matrixWrite cave i j newID)
(neighboringCavities pos cave)
else cave
end
in
change cave pos newID (matrixRead cave (fst pos) (snd pos))
end
and tryToPierce pos cave = let
val ncs = neighboringCavities pos cave
in
if hasDuplicates
(map (fn nc => matrixRead cave (fst nc) (snd nc)) ncs)
then cave
else pierce
pos
(foldl (fn (c, nc) => changeCavity c nc pos)
cave
ncs)
end
and pierceRandomly possibleHoles cave = (case possibleHoles
of nil => cave
| hole :: rest => pierceRandomly rest (tryToPierce hole cave)
(* end case *))
fun makeMaze n m = if not (odd n andalso odd m)
then raise Fail "n and m must be odd"
else let
fun init i j = if even i andalso even j
then Pt (i, j)
else Empty
val cave = makeMatrix n m init
val possibleHoles = concat (
for 0 n (fn i => concat (
for 0 m (fn j =>
if even i andalso even j
then nil
else [Pt (i, j)]
))
))
in
caveToMaze (pierceRandomly (shuffle possibleHoles) cave)
end
fun go (n, m) =
printStringMat (makeMaze n m)
end
structure Main =
struct
val iterations = 1
val n = 11
val m = 11
fun main _ = let
fun doit () = Benchmark.go (n, m)
fun lp 0 = ()
| lp n = (doit(); lp (n-1))
fun start () = lp iterations
in
start ()
end
end
val _ = Main.main (CommandLine.name (), CommandLine.arguments ())
Caught this in the benchmarks directory's parallel cml-merge
when the message size was set very high.
==================
WARNING: ThreadSanitizer: data race (pid=3448)
Read of size 8 at 0x7f78c4652ea8 by thread T5:
#0 majorGCscanLINKFRAMEpointer ../../gc/major-gc-scan.c:66 (a.out+0x20437)
#1 ScanMajorToSpace ../../gc/major-gc.c:503 (a.out+0x1e3a4)
#2 PromoteObj ../../gc/major-gc.c:420 (a.out+0x1e000)
#3 <null> <null> (a.out+0x4ab15)
#4 IdleVProc ../../vproc/vproc.c:673 (a.out+0x3f950)
#5 NewVProc ../../vproc/vproc.c:394 (a.out+0x3ecd5)
#6 InitWithLocation ../../cpu/topology.c:106 (a.out+0x4a3f3)
#7 <null> <null> (libtsan.so.0+0x296ad)
Previous write of size 8 at 0x7f78c4652ea8 by thread T3:
#0 ForwardObjMajor ../../gc/major-gc.c:52 (a.out+0x1cd17)
#1 majorGCscanBITPATpointer ../../gc/major-gc-scan.c:148 (a.out+0x207b0)
#2 ScanMajorToSpace ../../gc/major-gc.c:503 (a.out+0x1e3a4)
#3 MajorGC ../../gc/major-gc.c:322 (a.out+0x1d8ad)
#4 MinorGC ../../gc/minor-gc.c:527 (a.out+0x18822)
#5 RunManticore ../../vproc/apply.c:115 (a.out+0x43d29)
#6 IdleVProc ../../vproc/vproc.c:673 (a.out+0x3f950)
#7 NewVProc ../../vproc/vproc.c:394 (a.out+0x3ecd5)
#8 InitWithLocation ../../cpu/topology.c:106 (a.out+0x4a3f3)
#9 <null> <null> (libtsan.so.0+0x296ad)
Thread T5 (tid=3469, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x2bcee)
#1 ThreadCreate ../../include/os-threads.h:30 (a.out+0x49918)
#2 SpawnAt ../../cpu/topology.c:118 (a.out+0x4a49b)
#3 VProcInit ../../vproc/vproc.c:218 (a.out+0x3df67)
#4 main ../../misc/main.c:121 (a.out+0x414c5)
Thread T3 (tid=3465, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.0+0x2bcee)
#1 ThreadCreate ../../include/os-threads.h:30 (a.out+0x49918)
#2 SpawnAt ../../cpu/topology.c:118 (a.out+0x4a49b)
#3 VProcInit ../../vproc/vproc.c:218 (a.out+0x3df67)
#4 main ../../misc/main.c:121 (a.out+0x414c5)
There's a CPS eta-reduce pass already written in the partial_abort_stm
branch, which is run just before eta-expand.
It might be worth the effort to pull this optimization over to trunk, though I'm not sure what motivated @lematt1991 to implement this, i.e., is it meant to improve general programs, or clean-up some STM-specific transform?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.