Bug 1180984: JS GDB pretty-printers: Support Python 3. Fix 'Rooted' bitrot. r=sfink
☠☠ backed out by 90500c5ebfac ☠ ☠
authorJim Blandy <jimb@mozilla.com>
Tue, 28 Jul 2015 16:32:48 -0700
changeset 286758 c106728366642bcfb70f112f50f8630453611d8a
parent 286757 465793bc6fcf71beafea0bbf87f4d7ec23305f63
child 286759 e50e7d030a339f3364d540bcd5ea2e92b6bebadd
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1180984
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1180984: JS GDB pretty-printers: Support Python 3. Fix 'Rooted' bitrot. r=sfink
js/src/gdb/lib-for-tests/catcher.py
js/src/gdb/lib-for-tests/prologue.py
js/src/gdb/mozilla/JSSymbol.py
js/src/gdb/mozilla/Root.py
js/src/gdb/mozilla/asmjs.py
js/src/gdb/run-tests.py
--- a/js/src/gdb/lib-for-tests/catcher.py
+++ b/js/src/gdb/lib-for-tests/catcher.py
@@ -10,13 +10,13 @@
 # simple as possible!
 
 import os
 import sys
 import traceback
 try:
     # testlibdir is set on the GDB command line, via:
     # --eval-command python testlibdir=...
-    execfile(os.path.join(testlibdir, 'prologue.py'))
+    exec(open(os.path.join(testlibdir, 'prologue.py')).read())
 except Exception as err:
     sys.stderr.write('Error running GDB prologue:\n')
     traceback.print_exc()
     sys.exit(1)
--- a/js/src/gdb/lib-for-tests/prologue.py
+++ b/js/src/gdb/lib-for-tests/prologue.py
@@ -18,19 +18,19 @@ def run_fragment(fragment, function='bre
         assert bp.hit_count == 1
     finally:
         bp.delete()
     gdb.execute('frame 1')
 
 # Assert that |actual| is equal to |expected|; if not, complain in a helpful way.
 def assert_eq(actual, expected):
     if actual != expected:
-        raise AssertionError, """Unexpected result:
+        raise AssertionError("""Unexpected result:
 expected: %r
-actual:   %r""" % (expected, actual)
+actual:   %r""" % (expected, actual))
 
 # Assert that |value|'s pretty-printed form is |form|. If |value| is a
 # string, then evaluate it with gdb.parse_and_eval to produce a value.
 def assert_pretty(value, form):
     if isinstance(value, str):
         value = gdb.parse_and_eval(value)
     assert_eq(str(value), form)
 
@@ -39,37 +39,37 @@ def assert_pretty(value, form):
 def assert_subprinter_registered(printer, subprinter):
     # Match a line containing |printer| followed by a colon, and then a
     # series of more-indented lines containing |subprinter|.
 
     names = { 'printer': re.escape(printer), 'subprinter': re.escape(subprinter) }
     pat = r'^( +)%(printer)s *\n(\1 +.*\n)*\1 +%(subprinter)s *\n' % names
     output = gdb.execute('info pretty-printer', to_string=True)
     if not re.search(pat, output, re.MULTILINE):
-        raise AssertionError, ("assert_subprinter_registered failed to find pretty-printer:\n"
-                               "  %s:%s\n"
-                               "'info pretty-printer' says:\n"
-                               "%s" % (printer, subprinter, output))
+        raise AssertionError("assert_subprinter_registered failed to find pretty-printer:\n"
+                             "  %s:%s\n"
+                             "'info pretty-printer' says:\n"
+                             "%s" % (printer, subprinter, output))
 
 # Request full stack traces for Python errors.
 gdb.execute('set python print-stack full')
 
 # Tell GDB not to ask the user about the things we tell it to do.
 gdb.execute('set confirm off', False)
 
 # Some print settings that make testing easier.
 gdb.execute('set print static-members off')
 gdb.execute('set print address off')
 gdb.execute('set print pretty off')
 gdb.execute('set width 0')
 
 try:
     # testscript is set on the GDB command line, via:
     # --eval-command python testscript=...
-    execfile(testscript)
+    exec(open(testscript).read())
 except AssertionError as err:
     sys.stderr.write('\nAssertion traceback:\n')
     (t, v, tb) = sys.exc_info()
     traceback.print_tb(tb)
     sys.stderr.write('\nTest assertion failed:\n')
     sys.stderr.write(str(err))
     sys.exit(1)
 
--- a/js/src/gdb/mozilla/JSSymbol.py
+++ b/js/src/gdb/mozilla/JSSymbol.py
@@ -13,17 +13,17 @@ UniqueSymbol = 0xffffffff
 
 @ptr_pretty_printer("JS::Symbol")
 class JSSymbolPtr(mozilla.prettyprinters.Pointer):
     def __init__(self, value, cache):
         super(JSSymbolPtr, self).__init__(value, cache)
         self.value = value
 
     def to_string(self):
-        code = int(self.value['code_'])
+        code = int(self.value['code_']) & 0xffffffff
         desc = str(self.value['description_'])
         if code == InSymbolRegistry:
             return "Symbol.for({})".format(desc)
         elif code == UniqueSymbol:
             return "Symbol({})".format(desc)
         else:
             # Well-known symbol. Strip off the quotes added by the JSString *
             # pretty-printer.
--- a/js/src/gdb/mozilla/Root.py
+++ b/js/src/gdb/mozilla/Root.py
@@ -13,16 +13,20 @@ mozilla.prettyprinters.clear_module_prin
 class Common(object):
     # The name of the template member holding the referent.
     member = 'ptr'
 
     # If True, this is a handle type, and should be dereferenced. If False,
     # the template member holds the referent directly.
     handle = False
 
+    # If True, we should strip typedefs from our referent type. (Rooted<T>
+    # uses template magic that gives the referent a noisy type.)
+    strip_typedefs = False
+
     # Initialize a pretty-printer for |value|, using |cache|.
     #
     # If given, |content_printer| is a pretty-printer constructor to use for
     # this handle/root/etc.'s referent. Usually, we can just omit this argument
     # and let GDB choose a pretty-printer for the referent given its type, but
     # when the referent is a typedef of an integral type (say, |jsid| in a
     # non-|DEBUG| build), the GNU toolchain (at least) loses the typedef name,
     # and all we know about the referent is its fundamental integer type ---
@@ -37,28 +41,30 @@ class Common(object):
     def __init__(self, value, cache, content_printer=None):
         self.value = value
         self.cache = cache
         self.content_printer = content_printer
     def to_string(self):
         ptr = self.value[self.member]
         if self.handle:
             ptr = ptr.dereference()
+        if self.strip_typedefs:
+            ptr = ptr.cast(ptr.type.strip_typedefs())
         if self.content_printer:
             return self.content_printer(ptr, self.cache).to_string()
         else:
             # As of 2012-11, GDB suppresses printing pointers in replacement
             # values; see http://sourceware.org/ml/gdb/2012-11/msg00055.html
             # That means that simply returning the 'ptr' member won't work.
             # Instead, just invoke GDB's formatter ourselves.
             return str(ptr)
 
 @template_pretty_printer("JS::Rooted")
 class Rooted(Common):
-    pass
+    strip_typedefs = True
 
 @template_pretty_printer("JS::Handle")
 class Handle(Common):
     handle = True
 
 @template_pretty_printer("JS::MutableHandle")
 class MutableHandle(Common):
     handle = True
--- a/js/src/gdb/mozilla/asmjs.py
+++ b/js/src/gdb/mozilla/asmjs.py
@@ -20,17 +20,17 @@ def on_stop(event):
             sigaction_buffers[process] = buf
 
         # See if AsmJSFaultHandler is installed as the SIGSEGV signal action.
         sigaction_fn = gdb.parse_and_eval('__sigaction')
         sigaction_fn(SIGSEGV, 0, buf)
         AsmJSFaultHandler = gdb.parse_and_eval("AsmJSFaultHandler")
         if buf['__sigaction_handler']['sa_handler'] == AsmJSFaultHandler:
             # Advise the user that magic is happening.
-            print "js/src/gdb/mozilla/asmjs.py: Allowing AsmJSFaultHandler to run."
+            print("js/src/gdb/mozilla/asmjs.py: Allowing AsmJSFaultHandler to run.")
 
             # If AsmJSFaultHandler doesn't handle this segfault, it will unhook
             # itself and re-raise.
             gdb.execute("continue")
 
 def on_exited(event):
     if event.inferior in sigaction_buffers:
         del sigaction_buffers[event.inferior]
--- a/js/src/gdb/run-tests.py
+++ b/js/src/gdb/run-tests.py
@@ -156,17 +156,17 @@ class Test(TaskPool.Task):
         return [OPTIONS.gdb_executable,
                 '-nw',          # Don't create a window (unnecessary?)
                 '-nx',          # Don't read .gdbinit.
                 '--ex', 'add-auto-load-safe-path %s' % (OPTIONS.builddir,),
                 '--ex', 'set env LD_LIBRARY_PATH %s' % os.path.join(OPTIONS.objdir, 'js', 'src'),
                 '--ex', 'file %s' % (os.path.join(OPTIONS.builddir, 'gdb-tests'),),
                 '--eval-command', 'python testlibdir=%r' % (testlibdir,),
                 '--eval-command', 'python testscript=%r' % (self.test_path,),
-                '--eval-command', 'python execfile(%r)' % os.path.join(testlibdir, 'catcher.py')]
+                '--eval-command', 'python exec(open(%r).read())' % os.path.join(testlibdir, 'catcher.py')]
 
     def start(self, pipe, deadline):
         super(Test, self).start(pipe, deadline)
         if OPTIONS.show_cmd:
             self.summary.interleave_output(lambda: self.show_cmd(sys.stdout))
 
     def onStdout(self, text):
         self.stdout += text