Import Debian changes 20180207-1
[hcoop/debian/mlton.git] / basis-library / mlton / profile.sml
CommitLineData
7f918cf1
CE
1(* Copyright (C) 2003-2006, 2008 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 *
4 * MLton is released under a BSD-style license.
5 * See the file MLton-LICENSE for details.
6 *)
7
8structure MLtonProfile: MLTON_PROFILE =
9struct
10
11structure P = Primitive.MLton.Profile
12
13val gcState = Primitive.MLton.GCState.gcState
14
15val isOn = P.isOn
16
17structure Data =
18 struct
19 datatype t = T of {isCurrent: bool ref,
20 isFreed: bool ref,
21 raw: P.Data.t}
22
23 val all: t list ref = ref []
24
25 local
26 fun make f (T r) = f r
27 in
28 val isFreed = make #isFreed
29 val raw = make #raw
30 end
31
32 fun equals (d, d') =
33 isFreed d = isFreed d'
34
35 fun free (d as T {isCurrent, isFreed, raw, ...}) =
36 if not isOn
37 then ()
38 else
39 if !isFreed
40 then raise Fail "free of freed profile data"
41 else if !isCurrent
42 then raise Fail "free of current profile data"
43 else
44 (all := List.foldl (fn (d', ac) =>
45 if equals (d, d')
46 then ac
47 else d' :: ac) [] (!all)
48 ; P.Data.free (gcState, raw)
49 ; isFreed := true)
50
51 fun make (raw: P.Data.t): t =
52 T {isCurrent = ref false,
53 isFreed = ref false,
54 raw = raw}
55
56 fun malloc (): t =
57 let
58 val array =
59 if isOn
60 then P.Data.malloc gcState
61 else P.Data.dummy
62 val d = make array
63 val _ = all := d :: !all
64 in
65 d
66 end
67
68 fun write (T {isFreed, raw, ...}, file) =
69 if not isOn then
70 ()
71 else if !isFreed then
72 raise Fail "write of freed profile data"
73 else
74 P.Data.write (gcState, raw,
75 Primitive.NullString8.fromString
76 (String.nullTerm file))
77 end
78
79val r: Data.t ref = ref (Data.make P.Data.dummy)
80
81fun current () = !r
82
83fun setCurrent (d as Data.T {isCurrent, isFreed, raw, ...}) =
84 if not isOn
85 then ()
86 else
87 if !isFreed
88 then raise Fail "setCurrent of freed profile data"
89 else
90 let
91 val Data.T {isCurrent = ic, ...} = current ()
92 val _ = ic := false
93 val _ = isCurrent := true
94 val _ = r := d
95 val _ = P.setCurrent (gcState, raw)
96 in
97 ()
98 end
99
100fun withData (d: Data.t, f: unit -> 'a): 'a =
101 let
102 val old = current ()
103 val _ = setCurrent d
104 in
105 DynamicWind.wind (f, fn () => setCurrent old)
106 end
107
108fun init () = setCurrent (Data.make (P.getCurrent gcState))
109
110val _ =
111 if not isOn
112 then ()
113 else
114 let
115 val _ =
116 Cleaner.addNew
117 (Cleaner.atExit, fn () =>
118 (P.done gcState
119 ; Data.write (current (), "mlmon.out")
120 ; List.app (fn d => P.Data.free (gcState, Data.raw d))
121 (!Data.all)))
122 val _ =
123 Cleaner.addNew
124 (Cleaner.atLoadWorld, fn () =>
125 ((* In a new world, all of the old profiling data is invalid. *)
126 Data.all := []
127 ; init ()))
128 in
129 init ()
130 end
131
132end