169 lines
4.6 KiB
Lua
169 lines
4.6 KiB
Lua
-- debugging aid
|
|
|
|
---------------
|
|
-- FUNCTIONS --
|
|
---------------
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
-- function tracing asked in config file ?
|
|
-- if traceFunctions == true then
|
|
-- local function traceFunction(what)
|
|
-- debug.sethook()
|
|
-- local di = debug.getinfo(2)
|
|
-- --luaObject(di)
|
|
-- if di.name ~= nil and di.name ~= 'getmetatable' then
|
|
-- debugInfo(what .. " : " .. tostring(di.name) .. " : " .. tostring(di.short_src) .. " : " .. tostring(di.currentline))
|
|
-- end
|
|
-- debug.sethook(traceFunction, "cr")
|
|
-- end
|
|
-- debugInfo("turning debug hook on")
|
|
-- debug.sethook(traceFunction, "c")
|
|
--else
|
|
-- --debugInfo("turning debug hook off")
|
|
-- debug.sethook()
|
|
--end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
-- dump objects cycles for the given object
|
|
function dumpCycles(base, visitedSet, infos)
|
|
local function fullName(infos)
|
|
local result = ""
|
|
while infos do
|
|
result = infos.Name .. "." .. result
|
|
infos = infos.Parent
|
|
end
|
|
return result
|
|
end
|
|
if visitedSet == nil then
|
|
visitedSet = {}
|
|
end
|
|
if infos == nil then
|
|
infos = { Name = "root", Parent = nil }
|
|
end
|
|
for k, v in pairs(base) do
|
|
if v ~= _G._G then
|
|
if type(v) == "table" then
|
|
local newInfos = { Name = tostring(k), Parent = infos }
|
|
if visitedSet[v] then
|
|
debugInfo(fullName(visitedSet[v]) .. "is referenced by " .. fullName(newInfos))
|
|
else
|
|
visitedSet[v] = newInfos -- mark as visited
|
|
dumpCycles(v, visitedSet, newInfos)
|
|
visitedSet[v] = nil -- only intersted in cycles
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
-- display time taken to execute a function
|
|
function profileFunction(func, name)
|
|
assert(type(func) == "function")
|
|
if name == nil then
|
|
name = debug.getinfo(func).name
|
|
end
|
|
local startTime = nltime.getPreciseLocalTime()
|
|
func()
|
|
local endTime = nltime.getPreciseLocalTime()
|
|
--debugInfo(string.format("time for %s is %d", tostring(name), endTime - startTime))
|
|
end
|
|
|
|
-- display time taken to execute a function
|
|
function profileMethod(table, funcName, name)
|
|
assert(table)
|
|
assert(type(funcName) == "string")
|
|
assert(type(table[funcName]) == "function")
|
|
if name == nil then
|
|
name = select(debug.getinfo(table[funcName]).name, funcName)
|
|
end
|
|
local startTime = nltime.getLocalTime()
|
|
table[funcName](table)
|
|
local endTime = nltime.getLocalTime()
|
|
debugInfo(string.format("time for %s is %f", tostring(name), (endTime - startTime) / 1000))
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
-- add a break that is triggered when a value in a table has been changed
|
|
function addBreakOnChange(table, watchedKey)
|
|
assert(type(table) == "table")
|
|
local value = table[watchedKey]
|
|
assert(value ~= nil)
|
|
table[watchedKey] = nil
|
|
debugInfo("Adding break on change of key " .. tostring(watchedKey))
|
|
local mt = getmetatable(table)
|
|
local oldNewIndex
|
|
if mt then
|
|
oldNewIndex = mt.__newindex
|
|
end
|
|
local newMT
|
|
if mt then newMT = clone(mt) else newMT = {} end
|
|
-- WRITE
|
|
newMT.__newindex = function(table, key, newValue)
|
|
debugInfo('write')
|
|
if key == watchedKey then
|
|
value = newValue
|
|
debugInfo(debug.traceback())
|
|
debugWarning("<addBreakOnChange> Key " .. tostring(watchedKey) .. " changed to " .. tostring(value))
|
|
assert(nil)
|
|
elseif mt and mt.__newindex then
|
|
mt.__newindex(table, key, newValue)
|
|
else
|
|
rawset(table, key, newValue)
|
|
end
|
|
end
|
|
-- READ
|
|
newMT.__index = function(table, key)
|
|
debugInfo('read')
|
|
if key == watchedKey then
|
|
return value
|
|
elseif mt and mt.__index then
|
|
return mt.__index(table, key, value)
|
|
else
|
|
return rawget(table, key)
|
|
end
|
|
end
|
|
--
|
|
setmetatable(table, newMT)
|
|
end
|
|
|
|
----------
|
|
-- INIT --
|
|
----------
|
|
|
|
|
|
-- replace the assert function with a more verbose one
|
|
if oldAssert == nil then
|
|
oldAssert = assert
|
|
end
|
|
|
|
function assert(cond)
|
|
if not cond then
|
|
rawDebugInfo(colorTag(255, 0, 255) .. "ASSERTION FAILED !! ")
|
|
dumpCallStack(2);
|
|
error("")
|
|
end
|
|
end
|
|
|
|
|
|
local gcStartTime
|
|
|
|
-- special nico stuff : modified lua version calls "__notify_debug" when a garbage collection cycle occurs
|
|
function __notify_gc()
|
|
gcStartTime = nltime.getLocalTime()
|
|
end
|
|
function __notify_post_gc()
|
|
local deltaTime = nltime.getLocalTime() - gcStartTime
|
|
local used, threshold = gcinfo()
|
|
debugInfo(colorTag(255, 0, 0) .. string.format("** GC ** (%d ms) (used = %d kb, threshold = %d kb", deltaTime, used, threshold))
|
|
end
|
|
|
|
|
|
--testTable = { tata = 1, toto = 2 }
|
|
|
|
--addBreakOnChange(testTable, "tata")
|
|
|
|
--testTable.tutu = 2
|
|
--testTable.tata = testTable.tata + 20
|
|
|