Bug 645416, part 11 - Update GDB pretty-printers for symbols. r=jimb.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 23 Jun 2014 10:56:50 -0500
changeset 190278 edcb8617d09fe1f1eec5749e3c4e2912688fe49f
parent 190277 d8e2600e9aa3abe063ef443781f13586f023687f
child 190279 7171929b009012887c01b97d99766fe09a26029d
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjimb
bugs645416
milestone33.0a1
Bug 645416, part 11 - Update GDB pretty-printers for symbols. r=jimb.
js/src/gdb/moz.build
js/src/gdb/mozilla/JSSymbol.py
js/src/gdb/mozilla/autoload.py
js/src/gdb/mozilla/jsval.py
js/src/gdb/mozilla/prettyprinters.py
js/src/gdb/tests/test-JSSymbol.cpp
js/src/gdb/tests/test-JSSymbol.py
js/src/gdb/tests/test-jsval.cpp
js/src/gdb/tests/test-jsval.py
--- a/js/src/gdb/moz.build
+++ b/js/src/gdb/moz.build
@@ -6,16 +6,17 @@
 
 PROGRAM = 'gdb-tests'
 
 UNIFIED_SOURCES += [
     'gdb-tests.cpp',
     'tests/test-jsid.cpp',
     'tests/test-JSObject.cpp',
     'tests/test-JSString.cpp',
+    'tests/test-JSSymbol.cpp',
     'tests/test-jsval.cpp',
     'tests/test-prettyprinters.cpp',
     'tests/test-Root.cpp',
     'tests/typedef-printers.cpp',
 ]
 
 # Building against js_static requires that we declare mfbt sybols "exported"
 # on its behalf.
new file mode 100644
--- /dev/null
+++ b/js/src/gdb/mozilla/JSSymbol.py
@@ -0,0 +1,33 @@
+# Pretty-printer for SpiderMonkey symbols.
+
+import gdb
+import mozilla.prettyprinters
+from mozilla.prettyprinters import ptr_pretty_printer
+
+# Forget any printers from previous loads of this module.
+mozilla.prettyprinters.clear_module_printers(__name__)
+
+# JS::SymbolCode enumerators
+InSymbolRegistry = 0xfffffffe
+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_'])
+        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.
+            assert desc[0] == '"'
+            assert desc[-1] == '"'
+            return desc[1:-1]
+
--- a/js/src/gdb/mozilla/autoload.py
+++ b/js/src/gdb/mozilla/autoload.py
@@ -6,16 +6,17 @@ print("If they cause trouble, type: disa
 import gdb.printing
 import mozilla.prettyprinters
 
 # Import the pretty-printer modules. As a side effect, loading these
 # modules registers their printers with mozilla.prettyprinters.
 import mozilla.jsid
 import mozilla.JSObject
 import mozilla.JSString
+import mozilla.JSSymbol
 import mozilla.jsval
 import mozilla.Root
 
 # The user may have personal pretty-printers. Get those, too, if they exist.
 try:
     import my_mozilla_printers
 except ImportError:
     pass
--- a/js/src/gdb/mozilla/jsval.py
+++ b/js/src/gdb/mozilla/jsval.py
@@ -156,16 +156,17 @@ class jsvalTypeCache(object):
         # Capture the tag values.
         d = gdb.types.make_enum_dict(gdb.lookup_type('JSValueType'))
         self.DOUBLE    = d['JSVAL_TYPE_DOUBLE']
         self.INT32     = d['JSVAL_TYPE_INT32']
         self.UNDEFINED = d['JSVAL_TYPE_UNDEFINED']
         self.BOOLEAN   = d['JSVAL_TYPE_BOOLEAN']
         self.MAGIC     = d['JSVAL_TYPE_MAGIC']
         self.STRING    = d['JSVAL_TYPE_STRING']
+        self.SYMBOL    = d['JSVAL_TYPE_SYMBOL']
         self.NULL      = d['JSVAL_TYPE_NULL']
         self.OBJECT    = d['JSVAL_TYPE_OBJECT']
 
         # Let self.magic_names be an array whose i'th element is the name of
         # the i'th magic value.
         d = gdb.types.make_enum_dict(gdb.lookup_type('JSWhyMagic'))
         self.magic_names = list(range(max(d.values()) + 1))
         for (k,v) in d.items(): self.magic_names[v] = k
@@ -198,16 +199,18 @@ class jsval_layout(object):
         elif tag == self.jtc.MAGIC:
             value = self.box.as_uint32()
             if 0 <= value and value < len(self.jtc.magic_names):
                 return '$jsmagic(%s)' % (self.jtc.magic_names[value],)
             else:
                 return '$jsmagic(%d)' % (value,)
         elif tag == self.jtc.STRING:
             value = self.box.as_address().cast(self.cache.JSString_ptr_t)
+        elif tag == self.jtc.SYMBOL:
+            value = self.box.as_address().cast(self.cache.JSSymbol_ptr_t)
         elif tag == self.jtc.NULL:
             return 'JSVAL_NULL'
         elif tag == self.jtc.OBJECT:
             value = self.box.as_address().cast(self.cache.JSObject_ptr_t)
         elif tag == self.jtc.DOUBLE:
             value = self.value['asDouble']
         else:
             return '$jsval(unrecognized!)'
--- a/js/src/gdb/mozilla/prettyprinters.py
+++ b/js/src/gdb/mozilla/prettyprinters.py
@@ -169,16 +169,17 @@ class TypeCache(object):
         # Unfortunately, the Python interface doesn't allow us to specify
         # the objfile in whose scope lookups should occur. But simply
         # knowing that we need to lookup the types afresh is probably
         # enough.
         self.void_t = gdb.lookup_type('void')
         self.void_ptr_t = self.void_t.pointer()
         try:
             self.JSString_ptr_t = gdb.lookup_type('JSString').pointer()
+            self.JSSymbol_ptr_t = gdb.lookup_type('JS::Symbol').pointer()
             self.JSObject_ptr_t = gdb.lookup_type('JSObject').pointer()
         except gdb.error:
             raise NotSpiderMonkeyObjfileError
 
         self.mod_JSString = None
         self.mod_JSObject = None
         self.mod_jsval = None
 
new file mode 100644
--- /dev/null
+++ b/js/src/gdb/tests/test-JSSymbol.cpp
@@ -0,0 +1,20 @@
+#include "gdb-tests.h"
+#include "jsapi.h"
+
+FRAGMENT(JSSymbol, simple) {
+  using namespace JS;
+
+  RootedString hello(cx, JS_NewStringCopyZ(cx, "Hello!"));
+
+  Rooted<Symbol*> unique(cx, NewSymbol(cx, NullPtr()));
+  Rooted<Symbol*> unique_with_desc(cx, NewSymbol(cx, hello));
+  Rooted<Symbol*> registry(cx, GetSymbolFor(cx, hello));
+  Rooted<Symbol*> well_known(cx, GetWellKnownSymbol(cx, SymbolCode::iterator));
+
+  breakpoint();
+
+  (void) unique;
+  (void) unique_with_desc;
+  (void) registry;
+  (void) well_known;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/gdb/tests/test-JSSymbol.py
@@ -0,0 +1,10 @@
+# Printing JS::Symbols.
+
+assert_subprinter_registered('SpiderMonkey', 'ptr-to-JS::Symbol')
+
+run_fragment('JSSymbol.simple')
+
+assert_pretty('unique', 'Symbol()')
+assert_pretty('unique_with_desc', 'Symbol("Hello!")')
+assert_pretty('registry', 'Symbol.for("Hello!")')
+assert_pretty('well_known', 'Symbol.iterator')
--- a/js/src/gdb/tests/test-jsval.cpp
+++ b/js/src/gdb/tests/test-jsval.cpp
@@ -1,36 +1,40 @@
 #include "gdb-tests.h"
 #include "jsapi.h"
 
 FRAGMENT(jsval, simple) {
-  JS::Rooted<jsval> fortytwo(cx, INT_TO_JSVAL(42));
-  JS::Rooted<jsval> negone(cx, INT_TO_JSVAL(-1));
-  JS::Rooted<jsval> undefined(cx, JSVAL_VOID);
-  JS::Rooted<jsval> null(cx, JSVAL_NULL);
-  JS::Rooted<jsval> js_true(cx, JSVAL_TRUE);
-  JS::Rooted<jsval> js_false(cx, JSVAL_FALSE);
-  JS::Rooted<jsval> elements_hole(cx, js::MagicValue(JS_ELEMENTS_HOLE));
+  using namespace JS;
 
-  JS::Rooted<jsval> empty_string(cx);
+  RootedValue fortytwo(cx, Int32Value(42));
+  RootedValue negone(cx, Int32Value(-1));
+  RootedValue undefined(cx, UndefinedValue());
+  RootedValue null(cx, NullValue());
+  RootedValue js_true(cx, BooleanValue(true));
+  RootedValue js_false(cx, BooleanValue(false));
+  RootedValue elements_hole(cx, js::MagicValue(JS_ELEMENTS_HOLE));
+
+  RootedValue empty_string(cx);
   empty_string.setString(JS_NewStringCopyZ(cx, ""));
-  JS::Rooted<jsval> friendly_string(cx);
-  friendly_string.setString(JS_NewStringCopyZ(cx, "Hello!"));
+  RootedString hello(cx, JS_NewStringCopyZ(cx, "Hello!"));
+  RootedValue friendly_string(cx, StringValue(hello));
+  RootedValue symbol(cx, SymbolValue(GetSymbolFor(cx, hello)));
 
-  JS::Rooted<jsval> global(cx);
-  global.setObject(*JS::CurrentGlobalOrNull(cx));
+  RootedValue global(cx);
+  global.setObject(*CurrentGlobalOrNull(cx));
 
   // Some interesting value that floating-point won't munge.
-  JS::Rooted<jsval> onehundredthirtysevenonehundredtwentyeighths(cx, DOUBLE_TO_JSVAL(137.0 / 128.0));
+  RootedValue onehundredthirtysevenonehundredtwentyeighths(cx, DOUBLE_TO_JSVAL(137.0 / 128.0));
 
   breakpoint();
 
   (void) fortytwo;
   (void) negone;
   (void) undefined;
   (void) js_true;
   (void) js_false;
   (void) null;
   (void) elements_hole;
   (void) empty_string;
   (void) friendly_string;
+  (void) symbol;
   (void) global;
 }
--- a/js/src/gdb/tests/test-jsval.py
+++ b/js/src/gdb/tests/test-jsval.py
@@ -8,10 +8,11 @@ assert_pretty('fortytwo', '$jsval(42)')
 assert_pretty('negone', '$jsval(-1)')
 assert_pretty('undefined', 'JSVAL_VOID')
 assert_pretty('null', 'JSVAL_NULL')
 assert_pretty('js_true', 'JSVAL_TRUE')
 assert_pretty('js_false', 'JSVAL_FALSE')
 assert_pretty('elements_hole', '$jsmagic(JS_ELEMENTS_HOLE)')
 assert_pretty('empty_string', '$jsval("")')
 assert_pretty('friendly_string', '$jsval("Hello!")')
+assert_pretty('symbol', '$jsval(Symbol.for("Hello!"))')
 assert_pretty('global', '$jsval((JSObject *)  [object global] delegate)')
 assert_pretty('onehundredthirtysevenonehundredtwentyeighths', '$jsval(1.0703125)')