luat-sto.lua /size: 5113 b    last modification: 2021-10-28 13:50
1if not modules then modules = { } end modules ['luat-sto'] = {
2    version   = 1.001,
3    comment   = "companion to luat-lib.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9-- we could nil some function in the productionrun
10
11local type, next, setmetatable, getmetatable, collectgarbage = type, next, setmetatable, getmetatable, collectgarbage
12local gmatch, format = string.gmatch, string.format
13local serialize, concat, sortedhash = table.serialize, table.concat, table.sortedhash
14local setbytecode = lua.setbytecode
15local strippedloadstring = utilities.lua.strippedloadstring
16local loadstring = utilities.lua.loadstring
17local formatters = string.formatters
18
19local trace_storage  = false
20local report_storage = logs.reporter("system","storage")
21
22storage            = storage or { }
23local storage      = storage
24
25local data         = { }
26storage.data       = data
27
28storage.min        = 0 -- 500
29storage.max        = storage.min - 1
30storage.noftables  = storage.noftables or 0
31storage.nofmodules = storage.nofmodules or 0
32
33storage.mark       = utilities.storage.mark
34storage.allocate   = utilities.storage.allocate
35storage.marked     = utilities.storage.marked
36storage.strip      = false
37
38directives.register("system.compile.strip", function(v) storage.strip = v end)
39
40function storage.register(...)
41    local t = { ... }
42    local d = t[2]
43    if d then
44        storage.mark(d)
45    else
46        report_storage("fatal error: invalid storage %a",t[1])
47        os.exit()
48    end
49    data[#data+1] = t
50    return t
51end
52
53local n = 0 -- is that one used ?
54
55if environment.initex then
56
57    local function dump()
58        local max   = storage.max
59        local strip = storage.strip
60        for i=1,#data do
61            max = max + 1
62            local tabledata  = data[i]
63            local message    = tabledata[1]
64            local original   = tabledata[2]
65            local target     = tabledata[3]
66            local definition = utilities.tables.definetable(target,false,true)
67            local comment    = formatters["restoring %s from slot %s"](message,max)
68            if trace_storage then
69                comment = formatters["print('%s')"](comment)
70            else
71                comment = formatters["-- %s"](comment)
72            end
73            local dumped = serialize(original,target)
74            if trace_storage then
75                report_storage("saving %a in slot %a, size %s",message,max,#dumped)
76            end
77            -- we don't need tracing in such tables
78            dumped = concat({ definition, comment, dumped },"\n")
79            local code = nil
80            local name = formatters["slot %s (%s)"](max,name)
81            if LUAVERSION >= 5.3 then
82                local code = loadstring(dumped,name)
83                setbytecode(max,code,strip)
84            else
85                local code = strippedloadstring(dumped,name,strip)
86                setbytecode(max,code)
87            end
88            collectgarbage("step")
89        end
90        storage.max = max
91    end
92
93    lua.registerinitexfinalizer(dump,"dump storage")
94
95end
96
97statistics.register("stored bytecode data", function()
98    local nofbytecodes = CONTEXTLMTXMODE > 0 and status.luastate.bytecodes or status.luabytecodes
99    local nofmodules   = (storage.nofmodules > 0 and storage.nofmodules) or (nofbytecodes - lua.firstbytecode - 1)
100    local nofdumps     = (storage.noftables  > 0 and storage.noftables ) or storage.max-storage.min + 1
101    local tofmodules   = storage.tofmodules or 0
102    local tofdumps     = storage.toftables  or 0
103    if environment.initex then
104        local luautilities = utilities.lua
105        return format("%s modules, %s tables, %s chunks, %s chunks stripped (%s bytes)",
106            nofmodules,
107            nofdumps,
108            nofmodules + nofdumps,
109            luautilities.nofstrippedchunks or 0,
110            luautilities.nofstrippedbytes or 0
111        )
112    else
113        return format("%s modules (%0.3f sec), %s tables (%0.3f sec), %s chunks (%0.3f sec)",
114            nofmodules, tofmodules,
115            nofdumps, tofdumps,
116            nofmodules + nofdumps, tofmodules + tofdumps
117        )
118    end
119end)
120
121if lua.bytedata then
122    storage.register("lua/bytedata",lua.bytedata,"lua.bytedata")
123end
124
125-- Because the storage mechanism assumes tables, we define a table for storing
126-- (non table) values.
127
128storage.shared = storage.shared or { }
129
130storage.register("storage/shared", storage.shared, "storage.shared")
131
132local mark  = storage.mark
133
134if string.patterns     then                               mark(string.patterns)     end
135if string.formatters   then                               mark(string.formatters)   end
136if lpeg.patterns       then                               mark(lpeg.patterns)       end
137if os.env              then                               mark(os.env)              end
138if number.dimenfactors then                               mark(number.dimenfactors) end
139if libraries           then for k,v in next, libraries do mark(v)                   end end
140