Rev 158: Implement collapsing old-style classes. in http://bazaar.launchpad.net/~jameinel/meliae/mem-object-collection
John Arbash Meinel
john at arbash-meinel.com
Tue Dec 29 22:00:22 GMT 2009
At http://bazaar.launchpad.net/~jameinel/meliae/mem-object-collection
------------------------------------------------------------
revno: 158
revision-id: john at arbash-meinel.com-20091229215959-s26x0ut338x5oku2
parent: john at arbash-meinel.com-20091229213640-b76sv0ynf82hhxlb
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: mem-object-collection
timestamp: Tue 2009-12-29 15:59:59 -0600
message:
Implement collapsing old-style classes.
This means that we get proper type names as well as the dict itself being
part of the instance.
-------------- next part --------------
=== modified file 'meliae/_loader.pyx'
--- a/meliae/_loader.pyx 2009-12-29 21:34:51 +0000
+++ b/meliae/_loader.pyx 2009-12-29 21:59:59 +0000
@@ -327,6 +327,13 @@
def __get__(self):
return <object>(self._obj.type_str)
+ def __set__(self, value):
+ cdef PyObject *ptr
+ ptr = <PyObject *>value
+ Py_INCREF(ptr)
+ Py_DECREF(self._obj.type_str)
+ self._obj.type_str = ptr
+
property size:
"""The number of bytes allocated for this object."""
def __get__(self):
=== modified file 'meliae/loader.py'
--- a/meliae/loader.py 2009-12-29 21:36:40 +0000
+++ b/meliae/loader.py 2009-12-29 21:59:59 +0000
@@ -406,20 +406,27 @@
sys.stderr.write('checked %8d / %8d collapsed %8d \r'
% (item_idx, total, collapsed))
if obj.type_str == 'module' and len(obj) == 1:
- (dict_ref,) = obj.ref_list
+ (dict_obj,) = obj
+ if dict_obj.type_str != 'dict':
+ continue
extra_refs = []
else:
if len(obj) != 2:
continue
- (dict_ref, type_ref) = obj.ref_list
- type_obj = self.objs[type_ref]
- if (type_obj.type_str != 'type'
- or type_obj.value != obj.type_str):
+ obj_1, obj_2 = obj
+ if obj_1.type_str == 'dict' and obj_2.type_str == 'type':
+ # This is a new-style class
+ dict_obj = obj_1
+ type_obj = obj_2
+ elif (obj.type_str == 'instance'
+ and obj_1.type_str == 'classobj'
+ and obj_2.type_str == 'dict'):
+ # This is an old-style class
+ type_obj = obj_1
+ dict_obj = obj_2
+ else:
continue
- extra_refs = [type_ref]
- dict_obj = self.objs[dict_ref]
- if dict_obj.type_str != 'dict':
- continue
+ extra_refs = [type_obj.address]
if (dict_obj.num_referrers != 1
or dict_obj.referrers[0] != address):
continue
@@ -428,9 +435,11 @@
obj.ref_list = dict_obj.ref_list + extra_refs
obj.size = obj.size + dict_obj.size
obj.total_size = 0
+ if obj.type_str == 'instance':
+ obj.type_str = type_obj.value
# Now that all the data has been moved into the instance, remove
# the dict from the collection
- del self.objs[dict_ref]
+ del self.objs[dict_obj.address]
if self.show_progress:
sys.stderr.write('checked %8d / %8d collapsed %8d \n'
% (item_idx, total, collapsed))
=== modified file 'meliae/tests/test__loader.py'
--- a/meliae/tests/test__loader.py 2009-12-29 21:34:51 +0000
+++ b/meliae/tests/test__loader.py 2009-12-29 21:59:59 +0000
@@ -228,6 +228,12 @@
mop.value = 'a str'
self.assertEqual('a str', mop.value)
+ def test_type_str(self):
+ mop = self.moc.add(1234, 'type', 256, value='testval')
+ self.assertEqual('type', mop.type_str)
+ mop.type_str = 'difftype'
+ self.assertEqual('difftype', mop.type_str)
+
def test_name(self):
mop = self.moc.add(1234, 'type', 256, name='the name')
# 'name' entries get mapped as value
=== modified file 'meliae/tests/test_loader.py'
--- a/meliae/tests/test_loader.py 2009-12-29 21:34:51 +0000
+++ b/meliae/tests/test_loader.py 2009-12-29 21:59:59 +0000
@@ -72,6 +72,20 @@
'{"address": 15, "type": "dict", "size": 140, "len": 2, "refs": [5, 6, 9, 6]}',
]
+_old_instance_dump = [
+'{"address": 1, "type": "instance", "size": 36, "refs": [2, 3]}',
+'{"address": 3, "type": "dict", "size": 140, "len": 2, "refs": [4, 5, 6, 7]}',
+'{"address": 7, "type": "int", "size": 12, "value": 2, "refs": []}',
+'{"address": 6, "type": "str", "size": 25, "len": 1, "value": "b", "refs": []}',
+'{"address": 5, "type": "int", "size": 12, "value": 1, "refs": []}',
+'{"address": 4, "type": "str", "size": 25, "len": 1, "value": "a", "refs": []}',
+'{"address": 2, "type": "classobj", "size": 48, "name": "OldStyle"'
+ ', "refs": [8, 43839680, 9]}',
+'{"address": 9, "type": "str", "size": 32, "len": 8, "value": "OldStyle"'
+ ', "refs": []}',
+'{"address": 8, "type": "tuple", "size": 28, "len": 0, "refs": []}',
+]
+
class TestLoad(tests.TestCase):
@@ -270,6 +284,25 @@
self.assertEqual([5, 6, 9, 6], mod.ref_list)
self.assertFalse(15 in manager.objs)
+ def test_collapse_old_instance_dicts(self):
+ manager = loader.load(_old_instance_dump, show_prog=False)
+ instance = manager.objs[1]
+ self.assertEqual('instance', instance.type_str)
+ self.assertEqual(36, instance.size)
+ self.assertEqual([2, 3], instance.ref_list)
+ inst_dict = manager[3]
+ self.assertEqual(140, inst_dict.size)
+ self.assertEqual([4, 5, 6, 7], inst_dict.ref_list)
+ manager.compute_referrers()
+ manager.collapse_instance_dicts()
+ # The instance dict has been removed, and its references moved into the
+ # instance, further, the type has been updated from generic 'instance'
+ # to being 'OldStyle'.
+ self.assertFalse(3 in manager.objs)
+ self.assertEqual(176, instance.size)
+ self.assertEqual([4, 5, 6, 7, 2], instance.ref_list)
+ self.assertEqual('OldStyle', instance.type_str)
+
def test_expand_refs_as_dict(self):
manager = loader.load(_instance_dump, show_prog=False)
as_dict = manager.refs_as_dict(manager[15])
More information about the bazaar-commits
mailing list