| Index: tools/grokdump.py
|
| diff --git a/tools/grokdump.py b/tools/grokdump.py
|
| index 603453a852330a8bf30dd04fef4d8791e10f6def..804609b0a953e6579bdb586ecefcfbe53995debf 100755
|
| --- a/tools/grokdump.py
|
| +++ b/tools/grokdump.py
|
| @@ -1145,8 +1145,103 @@ class HeapObject(object):
|
|
|
|
|
| class Map(HeapObject):
|
| + def Decode(self, offset, size, value):
|
| + return (value >> offset) & ((1 << size) - 1)
|
| +
|
| + # Instance Sizes
|
| + def InstanceSizesOffset(self):
|
| + return self.heap.PointerSize()
|
| +
|
| + def InstanceSizeOffset(self):
|
| + return self.InstanceSizesOffset()
|
| +
|
| + def InObjectProperties(self):
|
| + return self.InstanceSizeOffset() + 1
|
| +
|
| + def PreAllocatedPropertyFields(self):
|
| + return self.InObjectProperties() + 1
|
| +
|
| + def VisitorId(self):
|
| + return self.PreAllocatedPropertyFields() + 1
|
| +
|
| + # Instance Attributes
|
| + def InstanceAttributesOffset(self):
|
| + return self.InstanceSizesOffset() + self.heap.IntSize()
|
| +
|
| def InstanceTypeOffset(self):
|
| - return self.heap.PointerSize() + self.heap.IntSize()
|
| + return self.InstanceAttributesOffset()
|
| +
|
| + def UnusedPropertyFieldsOffset(self):
|
| + return self.InstanceTypeOffset() + 1
|
| +
|
| + def BitFieldOffset(self):
|
| + return self.UnusedPropertyFieldsOffset() + 1
|
| +
|
| + def BitField2Offset(self):
|
| + return self.BitFieldOffset() + 1
|
| +
|
| + # Other fields
|
| + def PrototypeOffset(self):
|
| + return self.InstanceAttributesOffset() + self.heap.IntSize()
|
| +
|
| + def ConstructorOffset(self):
|
| + return self.PrototypeOffset() + self.heap.PointerSize()
|
| +
|
| + def TransitionsOrBackPointerOffset(self):
|
| + return self.ConstructorOffset() + self.heap.PointerSize()
|
| +
|
| + def DescriptorsOffset(self):
|
| + return self.TransitionsOrBackPointerOffset() + self.heap.PointerSize()
|
| +
|
| + def CodeCacheOffset(self):
|
| + return self.DescriptorsOffset() + self.heap.PointerSize()
|
| +
|
| + def DependentCodeOffset(self):
|
| + return self.CodeCacheOffset() + self.heap.PointerSize()
|
| +
|
| + def BitField3Offset(self):
|
| + return self.DependentCodeOffset() + self.heap.PointerSize()
|
| +
|
| + def ReadByte(self, offset):
|
| + return self.heap.reader.ReadU8(self.address + offset)
|
| +
|
| + def Print(self):
|
| + print "Map(%08x)" % (self.address)
|
| + print "- size: %d, inobject: %d, preallocated: %d, visitor: %d" % (
|
| + self.ReadByte(self.InstanceSizeOffset()),
|
| + self.ReadByte(self.InObjectProperties()),
|
| + self.ReadByte(self.PreAllocatedPropertyFields()),
|
| + self.VisitorId())
|
| +
|
| + bitfield = self.ReadByte(self.BitFieldOffset())
|
| + bitfield2 = self.ReadByte(self.BitField2Offset())
|
| + print "- %s, unused: %d, bf: %d, bf2: %d" % (
|
| + INSTANCE_TYPES[self.ReadByte(self.InstanceTypeOffset())],
|
| + self.ReadByte(self.UnusedPropertyFieldsOffset()),
|
| + bitfield, bitfield2)
|
| +
|
| + print "- kind: %s" % (self.Decode(3, 5, bitfield2))
|
| +
|
| + bitfield3 = self.ObjectField(self.BitField3Offset())
|
| + print "- EnumLength: %d NumberOfOwnDescriptors: %d OwnsDescriptors: %s" % (
|
| + self.Decode(0, 11, bitfield3),
|
| + self.Decode(11, 11, bitfield3),
|
| + self.Decode(25, 1, bitfield3))
|
| + print "- IsShared: %s" % (self.Decode(22, 1, bitfield3))
|
| + print "- FunctionWithPrototype: %s" % (self.Decode(23, 1, bitfield3))
|
| + print "- DictionaryMap: %s" % (self.Decode(24, 1, bitfield3))
|
| +
|
| + descriptors = self.ObjectField(self.DescriptorsOffset())
|
| + if descriptors.__class__ == FixedArray:
|
| + DescriptorArray(descriptors).Print()
|
| + else:
|
| + print "Descriptors: %s" % (descriptors)
|
| +
|
| + transitions = self.ObjectField(self.TransitionsOrBackPointerOffset())
|
| + if transitions.__class__ == FixedArray:
|
| + TransitionArray(transitions).Print()
|
| + else:
|
| + print "TransitionsOrBackPointer: %s" % (transitions)
|
|
|
| def __init__(self, heap, map, address):
|
| HeapObject.__init__(self, heap, map, address)
|
| @@ -1280,6 +1375,12 @@ class FixedArray(HeapObject):
|
| def ElementsOffset(self):
|
| return self.heap.PointerSize() * 2
|
|
|
| + def MemberOffset(self, i):
|
| + return self.ElementsOffset() + self.heap.PointerSize() * i
|
| +
|
| + def Get(self, i):
|
| + return self.ObjectField(self.MemberOffset(i))
|
| +
|
| def __init__(self, heap, map, address):
|
| HeapObject.__init__(self, heap, map, address)
|
| self.length = self.SmiField(self.LengthOffset())
|
| @@ -1305,6 +1406,111 @@ class FixedArray(HeapObject):
|
| return "FixedArray(%08x, length=%d)" % (self.address, self.length)
|
|
|
|
|
| +class DescriptorArray(object):
|
| + def __init__(self, array):
|
| + self.array = array
|
| +
|
| + def Length(self):
|
| + return self.array.Get(0)
|
| +
|
| + def Decode(self, offset, size, value):
|
| + return (value >> offset) & ((1 << size) - 1)
|
| +
|
| + TYPES = [
|
| + "normal",
|
| + "field",
|
| + "function",
|
| + "callbacks"
|
| + ]
|
| +
|
| + def Type(self, value):
|
| + return DescriptorArray.TYPES[self.Decode(0, 3, value)]
|
| +
|
| + def Attributes(self, value):
|
| + attributes = self.Decode(3, 3, value)
|
| + result = []
|
| + if (attributes & 0): result += ["ReadOnly"]
|
| + if (attributes & 1): result += ["DontEnum"]
|
| + if (attributes & 2): result += ["DontDelete"]
|
| + return "[" + (",".join(result)) + "]"
|
| +
|
| + def Deleted(self, value):
|
| + return self.Decode(6, 1, value) == 1
|
| +
|
| + def Storage(self, value):
|
| + return self.Decode(7, 11, value)
|
| +
|
| + def Pointer(self, value):
|
| + return self.Decode(18, 11, value)
|
| +
|
| + def Details(self, di, value):
|
| + return (
|
| + di,
|
| + self.Type(value),
|
| + self.Attributes(value),
|
| + self.Storage(value),
|
| + self.Pointer(value)
|
| + )
|
| +
|
| +
|
| + def Print(self):
|
| + length = self.Length()
|
| + array = self.array
|
| +
|
| + print "Descriptors(%08x, length=%d)" % (array.address, length)
|
| + print "[et] %s" % (array.Get(1))
|
| +
|
| + for di in xrange(length):
|
| + i = 2 + di * 3
|
| + print "0x%x" % (array.address + array.MemberOffset(i))
|
| + print "[%i] name: %s" % (di, array.Get(i + 0))
|
| + print "[%i] details: %s %s enum %i pointer %i" % \
|
| + self.Details(di, array.Get(i + 1))
|
| + print "[%i] value: %s" % (di, array.Get(i + 2))
|
| +
|
| + end = self.array.length // 3
|
| + if length != end:
|
| + print "[%i-%i] slack descriptors" % (length, end)
|
| +
|
| +
|
| +class TransitionArray(object):
|
| + def __init__(self, array):
|
| + self.array = array
|
| +
|
| + def IsSimpleTransition(self):
|
| + return self.array.length <= 2
|
| +
|
| + def Length(self):
|
| + # SimpleTransition cases
|
| + if self.IsSimpleTransition():
|
| + return self.array.length - 1
|
| + return (self.array.length - 3) // 2
|
| +
|
| + def Print(self):
|
| + length = self.Length()
|
| + array = self.array
|
| +
|
| + print "Transitions(%08x, length=%d)" % (array.address, length)
|
| + print "[backpointer] %s" % (array.Get(0))
|
| + if self.IsSimpleTransition():
|
| + if length == 1:
|
| + print "[simple target] %s" % (array.Get(1))
|
| + return
|
| +
|
| + elements = array.Get(1)
|
| + if elements is not None:
|
| + print "[elements ] %s" % (elements)
|
| +
|
| + prototype = array.Get(2)
|
| + if prototype is not None:
|
| + print "[prototype ] %s" % (prototype)
|
| +
|
| + for di in xrange(length):
|
| + i = 3 + di * 2
|
| + print "[%i] symbol: %s" % (di, array.Get(i + 0))
|
| + print "[%i] target: %s" % (di, array.Get(i + 1))
|
| +
|
| +
|
| class JSFunction(HeapObject):
|
| def CodeEntryOffset(self):
|
| return 3 * self.heap.PointerSize()
|
| @@ -1720,6 +1926,30 @@ class InspectionShell(cmd.Cmd):
|
| else:
|
| print "Address cannot be interpreted as object!"
|
|
|
| + def do_do_desc(self, address):
|
| + """
|
| + Print a descriptor array in a readable format.
|
| + """
|
| + start = int(address, 16)
|
| + if ((start & 1) == 1): start = start + 1
|
| + DescriptorArray(FixedArray(self.heap, None, start)).Print()
|
| +
|
| + def do_do_map(self, address):
|
| + """
|
| + Print a descriptor array in a readable format.
|
| + """
|
| + start = int(address, 16)
|
| + if ((start & 1) == 1): start = start - 1
|
| + Map(self.heap, None, start).Print()
|
| +
|
| + def do_do_trans(self, address):
|
| + """
|
| + Print a transition array in a readable format.
|
| + """
|
| + start = int(address, 16)
|
| + if ((start & 1) == 1): start = start - 1
|
| + TransitionArray(FixedArray(self.heap, None, start)).Print()
|
| +
|
| def do_dp(self, address):
|
| """
|
| Interpret memory at the given address as being on a V8 heap page
|
|
|