1# Pretty-printers for InterpreterRegs.
2
3import gdb
4import mozilla.prettyprinters as prettyprinters
5
6prettyprinters.clear_module_printers(__name__)
7
8from mozilla.prettyprinters import pretty_printer
9
10# Cache information about the Interpreter types for this objfile.
11class InterpreterTypeCache(object):
12    def __init__(self):
13        self.tValue = gdb.lookup_type('JS::Value')
14        self.tJSOp = gdb.lookup_type('JSOp')
15        self.tScriptFrameIterData = gdb.lookup_type('js::ScriptFrameIter::Data')
16        self.tInterpreterFrame = gdb.lookup_type('js::InterpreterFrame')
17        self.tBaselineFrame = gdb.lookup_type('js::jit::BaselineFrame')
18        self.tRematerializedFrame = gdb.lookup_type('js::jit::RematerializedFrame')
19        self.tDebugFrame = gdb.lookup_type('js::wasm::DebugFrame')
20
21@pretty_printer('js::InterpreterRegs')
22class InterpreterRegs(object):
23    def __init__(self, value, cache):
24        self.value = value
25        self.cache = cache
26        if not cache.mod_Interpreter:
27            cache.mod_Interpreter = InterpreterTypeCache()
28        self.itc = cache.mod_Interpreter
29
30    # There's basically no way to co-operate with 'set print pretty' (how would
31    # you get the current level of indentation?), so we don't even bother
32    # trying. No 'children', just 'to_string'.
33    def to_string(self):
34        fp_ = 'fp_ = {}'.format(self.value['fp_'])
35        slots = (self.value['fp_'] + 1).cast(self.itc.tValue.pointer())
36        sp = 'sp = fp_.slots() + {}'.format(self.value['sp'] - slots)
37        pc = self.value['pc']
38        try:
39            opcode = pc.dereference().cast(self.itc.tJSOp)
40        except:
41            opcode = 'bad pc'
42        pc = 'pc = {} ({})'.format(pc.cast(self.cache.void_ptr_t), opcode)
43        return '{{ {}, {}, {} }}'.format(fp_, sp, pc)
44
45@pretty_printer('js::AbstractFramePtr')
46class AbstractFramePtr(object):
47    Tag_ScriptFrameIterData = 0x0
48    Tag_InterpreterFrame = 0x1
49    Tag_BaselineFrame = 0x2
50    Tag_RematerializedFrame = 0x3
51    Tag_WasmDebugFrame = 0x4
52    TagMask = 0x7
53
54    def __init__(self, value, cache):
55        self.value = value
56        self.cache = cache
57        if not cache.mod_Interpreter:
58            cache.mod_Interpreter = InterpreterTypeCache()
59        self.itc = cache.mod_Interpreter
60
61    def to_string(self):
62        ptr = self.value['ptr_']
63        tag = ptr & AbstractFramePtr.TagMask
64        ptr = ptr & ~AbstractFramePtr.TagMask
65        if tag == AbstractFramePtr.Tag_ScriptFrameIterData:
66            label = 'js::ScriptFrameIter::Data'
67            ptr = ptr.cast(self.itc.tScriptFrameIterData.pointer())
68        if tag == AbstractFramePtr.Tag_InterpreterFrame:
69            label = 'js::InterpreterFrame'
70            ptr = ptr.cast(self.itc.tInterpreterFrame.pointer())
71        if tag == AbstractFramePtr.Tag_BaselineFrame:
72            label = 'js::jit::BaselineFrame'
73            ptr = ptr.cast(self.itc.tBaselineFrame.pointer())
74        if tag == AbstractFramePtr.Tag_RematerializedFrame:
75            label = 'js::jit::RematerializedFrame'
76            ptr = ptr.cast(self.itc.tRematerializedFrame.pointer())
77        if tag == AbstractFramePtr.Tag_WasmDebugFrame:
78            label = 'js::wasm::DebugFrame'
79            ptr = ptr.cast(self.itc.tDebugFrame.pointer())
80        return 'AbstractFramePtr (({} *) {})'.format(label, ptr)
81
82    # Provide the ptr_ field as a child, so it prints after the pretty string
83    # provided above.
84    def children(self):
85        yield ('ptr_', self.value['ptr_'])
86