Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/tools/stackdbg.py
2723 views
1
#!usr/bin/python3
2
"""
3
To use this command, simply run the command:
4
`command script import /path/to/your/game-engine/Client/Luau/tools/stackdbg.py`
5
in the `lldb` interpreter. You can also add it to your .lldbinit file to have it be
6
automatically imported.
7
8
If using vscode, you can add the above command to your launch.json under `preRunCommands` for the appropriate target. For example:
9
{
10
"name": "Luau.UnitTest",
11
"type": "lldb",
12
"request": "launch",
13
"program": "${workspaceFolder}/build/ninja/common-tests/noopt/Luau/Luau.UnitTest",
14
"preRunCommands": [
15
"command script import ${workspaceFolder}/Client/Luau/tools/stackdbg.py"
16
],
17
}
18
19
Once this is loaded,
20
`(lldb) help stack`
21
or
22
`(lldb) stack -h
23
or
24
`(lldb) stack --help
25
26
can get you started
27
"""
28
29
import lldb
30
import functools
31
import argparse
32
import shlex
33
34
# Dumps the collected frame data
35
def dump(collected):
36
for (frame_name, size_in_kb, live_size_kb, variables) in collected:
37
print(f'{frame_name}, locals: {size_in_kb}kb, fp-sp: {live_size_kb}kb')
38
for (var_name, var_size, variable_obj) in variables:
39
print(f' {var_name}, {var_size} bytes')
40
41
def dbg_stack_pressure(frame, frames_to_show = 5, sort_frames = False, vars_to_show = 5, sort_vars = True):
42
totalKb = 0
43
collect = []
44
for f in frame.thread:
45
frame_name = f.GetFunctionName()
46
variables = [ (v.GetName(), v.GetByteSize(), v) for v in f.get_locals() ]
47
if sort_vars:
48
variables.sort(key = lambda x: x[1], reverse = True)
49
size_in_kb = functools.reduce(lambda x,y : x + y[1], variables, 0) / 1024
50
51
fp = f.GetFP()
52
sp = f.GetSP()
53
live_size_kb = round((fp - sp) / 1024, 2)
54
55
size_in_kb = round(size_in_kb, 2)
56
totalKb += size_in_kb
57
collect.append((frame_name, size_in_kb, live_size_kb, variables[:vars_to_show]))
58
if sort_frames:
59
collect.sort(key = lambda x: x[1], reverse = True)
60
61
print("******************** Report Stack Usage ********************")
62
totalMb = round(totalKb / 1024, 2)
63
print(f'{len(frame.thread)} stack frames used {totalMb}MB')
64
dump(collect[:frames_to_show])
65
66
def stack(debugger, command, result, internal_dict):
67
"""
68
usage: [-h] [-f FRAMES] [-fd] [-v VARS] [-vd]
69
70
optional arguments:
71
-h, --help show this help message and exit
72
-f FRAMES, --frames FRAMES
73
How many stack frames to display
74
-fd, --sort_frames Sort frames
75
-v VARS, --vars VARS How many variables per frame to display
76
-vd, --sort_vars Sort frames
77
"""
78
79
frame = debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
80
args = shlex.split(command)
81
argparser = argparse.ArgumentParser(allow_abbrev = True)
82
argparser.add_argument("-f", "--frames", required=False, help="How many stack frames to display", default=5, type=int)
83
argparser.add_argument("-fd", "--sort_frames", required=False, help="Sort frames in descending order of stack usage", action="store_true", default=False)
84
argparser.add_argument("-v", "--vars", required=False, help="How many variables per frame to display", default=5, type=int)
85
argparser.add_argument("-vd", "--sort_vars", required=False, help="Sort locals in descending order of stack usage ", action="store_true", default=False)
86
87
args = argparser.parse_args(args)
88
dbg_stack_pressure(frame, frames_to_show=args.frames, sort_frames=args.sort_frames, vars_to_show=args.vars, sort_vars=args.sort_vars)
89
90
# Initialization code to add commands
91
def __lldb_init_module(debugger, internal_dict):
92
debugger.HandleCommand('command script add -f stackdbg.stack stack')
93
print("The 'stack' python command has been installed and is ready for use.")
94
95
96