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