Bug 1559072: Revert GDB python bindings to old boxing format r=sfink
authorIain Ireland <iireland@mozilla.com>
Tue, 25 Jun 2019 18:06:41 +0000
changeset 542995 eecb579563f7ab63376d5fd72ebf16ca0b672fc7
parent 542994 06eaa532a2da1eeb166d2ac0989d14af4f981b91
child 542996 01dd4bf87d24ac6492bddbbd28bb00021a6e6d23
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1559072
milestone69.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 1559072: Revert GDB python bindings to old boxing format r=sfink Depends on D35548 Differential Revision: https://phabricator.services.mozilla.com/D35549
js/src/gdb/mozilla/jsval.py
js/src/gdb/tests/test-jsval.py
--- a/js/src/gdb/mozilla/jsval.py
+++ b/js/src/gdb/mozilla/jsval.py
@@ -80,42 +80,42 @@ class Box(object):
             self.asBits = self.asBits + (1 << 64)
 
     # Return this value's type tag.
     def tag(self): raise NotImplementedError
 
     # Return this value as a 32-bit integer, double, or address.
     def as_uint32(self): raise NotImplementedError
 
-    def as_double(self): raise NotImplementedError
+    def as_double(self):
+        packed = struct.pack("q", self.asBits)
+        (unpacked,) = struct.unpack("d", packed)
+        return unpacked
 
     def as_address(self): raise NotImplementedError
 
 
 class Punbox(Box):
     # Packed non-number boxing --- the format used on x86_64. It would be nice to
     # simply call Value::toInt32, etc. here, but the debugger is likely to see many
     # Values, and doing several inferior calls for each one seems like a bad idea.
 
+    FULL_WIDTH = 64
     TAG_SHIFT = 47
     PAYLOAD_MASK = (1 << TAG_SHIFT) - 1
-    TAG_MAX_NON_DOUBLE = 0xe
-    DOUBLE_ADJUST = 0x0007FFFFFFFFFFFF
+    TAG_MASK = (1 << (FULL_WIDTH - TAG_SHIFT)) - 1
+    TAG_MAX_DOUBLE = 0x1fff0
+    TAG_TYPE_MASK = 0x0000f
 
     def tag(self):
-        tag = int(self.asBits >> Punbox.TAG_SHIFT)
-        if tag > Punbox.TAG_MAX_NON_DOUBLE:
+        tag = self.asBits >> Punbox.TAG_SHIFT
+        if tag <= Punbox.TAG_MAX_DOUBLE:
             return self.jtc.DOUBLE
         else:
-            return self.jtc.tagMap[tag]
-
-    def as_double(self):
-        packed = struct.pack("q", self.asBits - Punbox.DOUBLE_ADJUST)
-        (unpacked,) = struct.unpack("d", packed)
-        return unpacked
+            return tag & Punbox.TAG_TYPE_MASK
 
     def as_uint32(self): return int(self.asBits & ((1 << 32) - 1))
 
     def as_address(self): return gdb.Value(self.asBits & Punbox.PAYLOAD_MASK)
 
 
 class Nunbox(Box):
     TAG_SHIFT = 32
@@ -124,81 +124,56 @@ class Nunbox(Box):
     TAG_TYPE_MASK = 0x0000000f
 
     def tag(self):
         tag = self.asBits >> Nunbox.TAG_SHIFT
         if tag < Nunbox.TAG_CLEAR:
             return self.jtc.DOUBLE
         return tag & Nunbox.TAG_TYPE_MASK
 
-    def as_double(self):
-        packed = struct.pack("q", self.asBits)
-        (unpacked,) = struct.unpack("d", packed)
-        return unpacked
-
     def as_uint32(self): return int(self.asBits & Nunbox.PAYLOAD_MASK)
 
     def as_address(self): return gdb.Value(self.asBits & Nunbox.PAYLOAD_MASK)
 
 
 class JSValueTypeCache(object):
     # Cache information about the Value type for this objfile.
 
     def __init__(self, cache):
         # Capture the tag values.
         d = gdb.types.make_enum_dict(gdb.lookup_type('JSValueType'))
 
         # The enum keys are prefixed when building with some compilers (clang at
         # a minimum), so use a helper function to handle either key format.
-        def getter(enum_dict, prefix):
-            def get(key):
-                val = enum_dict.get(key)
-                if val is not None:
-                    return val
-                return enum_dict[prefix + key]
-            return get
+        def get(key):
+            val = d.get(key)
+            if val is not None:
+                return val
+            return d['JSValueType::' + key]
 
-        getType = getter(d, 'JSValueType::')
-        self.DOUBLE = getType('JSVAL_TYPE_DOUBLE')
-        self.INT32 = getType('JSVAL_TYPE_INT32')
-        self.UNDEFINED = getType('JSVAL_TYPE_UNDEFINED')
-        self.BOOLEAN = getType('JSVAL_TYPE_BOOLEAN')
-        self.MAGIC = getType('JSVAL_TYPE_MAGIC')
-        self.STRING = getType('JSVAL_TYPE_STRING')
-        self.SYMBOL = getType('JSVAL_TYPE_SYMBOL')
-        self.BIGINT = getType('JSVAL_TYPE_BIGINT')
-        self.NULL = getType('JSVAL_TYPE_NULL')
-        self.OBJECT = getType('JSVAL_TYPE_OBJECT')
+        self.DOUBLE = get('JSVAL_TYPE_DOUBLE')
+        self.INT32 = get('JSVAL_TYPE_INT32')
+        self.UNDEFINED = get('JSVAL_TYPE_UNDEFINED')
+        self.BOOLEAN = get('JSVAL_TYPE_BOOLEAN')
+        self.MAGIC = get('JSVAL_TYPE_MAGIC')
+        self.STRING = get('JSVAL_TYPE_STRING')
+        self.SYMBOL = get('JSVAL_TYPE_SYMBOL')
+        self.BIGINT = get('JSVAL_TYPE_BIGINT')
+        self.NULL = get('JSVAL_TYPE_NULL')
+        self.OBJECT = get('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
 
         # Choose an unboxing scheme for this architecture.
-        if cache.void_ptr_t.sizeof == 4:
-            self.boxer = Nunbox
-        else:
-            self.boxer = Punbox
-
-            # Type and Tag do not line up for Punbox
-            d2 = gdb.types.make_enum_dict(gdb.lookup_type('JSValueTag'))
-            getTag = getter(d2, 'JSValueTag::')
-            self.tagMap = {}
-            self.tagMap[getTag('JSVAL_TAG_INT32')] = self.INT32
-            self.tagMap[getTag('JSVAL_TAG_UNDEFINED')] = self.UNDEFINED
-            self.tagMap[getTag('JSVAL_TAG_BOOLEAN')] = self.BOOLEAN
-            self.tagMap[getTag('JSVAL_TAG_MAGIC')] = self.MAGIC
-            self.tagMap[getTag('JSVAL_TAG_STRING')] = self.STRING
-            self.tagMap[getTag('JSVAL_TAG_SYMBOL')] = self.SYMBOL
-            self.tagMap[getTag('JSVAL_TAG_BIGINT')] = self.BIGINT
-            self.tagMap[getTag('JSVAL_TAG_NULL')] = self.NULL
-            self.tagMap[getTag('JSVAL_TAG_OBJECT')] = self.OBJECT
+        self.boxer = Punbox if cache.void_ptr_t.sizeof == 8 else Nunbox
 
 
 @pretty_printer('JS::Value')
 class JSValue(object):
     def __init__(self, value, cache):
         # Save the generic typecache, and create our own, if we haven't already.
         self.cache = cache
         if not cache.mod_JS_Value:
--- a/js/src/gdb/tests/test-jsval.py
+++ b/js/src/gdb/tests/test-jsval.py
@@ -1,9 +1,8 @@
-
 # Basic unit tests for jsval pretty-printer.
 # flake8: noqa: F821
 
 assert_subprinter_registered('SpiderMonkey', 'JS::Value')
 
 run_fragment('jsval.simple')
 
 assert_pretty('fortytwo', '$JS::Int32Value(42)')