| 1 | #!/usr/bin/env python2
 | 
| 2 | """
 | 
| 3 | classes_gc.py - Test out field masks
 | 
| 4 | """
 | 
| 5 | from __future__ import print_function
 | 
| 6 | 
 | 
| 7 | import os
 | 
| 8 | 
 | 
| 9 | from mycpp import mylib
 | 
| 10 | from mycpp.mylib import log
 | 
| 11 | 
 | 
| 12 | from typing import List, Dict
 | 
| 13 | 
 | 
| 14 | 
 | 
| 15 | class Opaque(object):
 | 
| 16 | 
 | 
| 17 |     def __init__(self):
 | 
| 18 |         # type: () -> None
 | 
| 19 |         self.i = 0
 | 
| 20 | 
 | 
| 21 | 
 | 
| 22 | class OpaqueBase(object):
 | 
| 23 | 
 | 
| 24 |     def __init__(self):
 | 
| 25 |         # type: () -> None
 | 
| 26 |         self.j = 0
 | 
| 27 | 
 | 
| 28 | 
 | 
| 29 | class OpaqueDerived(OpaqueBase):
 | 
| 30 | 
 | 
| 31 |     def __init__(self):
 | 
| 32 |         # type: () -> None
 | 
| 33 |         OpaqueBase.__init__(self)
 | 
| 34 |         self.k = 0
 | 
| 35 | 
 | 
| 36 | 
 | 
| 37 | class Pointers(object):
 | 
| 38 | 
 | 
| 39 |     def __init__(self):
 | 
| 40 |         # type: () -> None
 | 
| 41 | 
 | 
| 42 |         # Make sure fields are sorted!
 | 
| 43 |         self.i = 0
 | 
| 44 |         self.s = 'S'
 | 
| 45 |         self.j = 42
 | 
| 46 |         self.t = 'T'
 | 
| 47 | 
 | 
| 48 | 
 | 
| 49 | class PointersBase(object):
 | 
| 50 | 
 | 
| 51 |     def __init__(self):
 | 
| 52 |         # type: () -> None
 | 
| 53 |         self.i = 0
 | 
| 54 |         self.s = 'S'
 | 
| 55 | 
 | 
| 56 | 
 | 
| 57 | class PointersDerived(PointersBase):
 | 
| 58 | 
 | 
| 59 |     def __init__(self):
 | 
| 60 |         # type: () -> None
 | 
| 61 |         PointersBase.__init__(self)
 | 
| 62 |         self.j = 42
 | 
| 63 |         self.t = 'T'
 | 
| 64 | 
 | 
| 65 | 
 | 
| 66 | class BaseWithMethod(object):
 | 
| 67 | 
 | 
| 68 |     def __init__(self):
 | 
| 69 |         # type: () -> None
 | 
| 70 |         self.i = 0
 | 
| 71 |         self.s = 'S'
 | 
| 72 | 
 | 
| 73 |     def Method(self):
 | 
| 74 |         # type: () -> int
 | 
| 75 |         return 42
 | 
| 76 | 
 | 
| 77 | 
 | 
| 78 | class DerivedWithMethod(BaseWithMethod):
 | 
| 79 | 
 | 
| 80 |     def __init__(self):
 | 
| 81 |         # type: () -> None
 | 
| 82 |         BaseWithMethod.__init__(self)
 | 
| 83 |         self.j = 42
 | 
| 84 |         self.t = 'T'
 | 
| 85 |         self.u = 'U'
 | 
| 86 | 
 | 
| 87 |     def Method(self):
 | 
| 88 |         # type: () -> int
 | 
| 89 |         return 99
 | 
| 90 | 
 | 
| 91 | 
 | 
| 92 | #
 | 
| 93 | # Regression for off-by-one bug in Tag::Scanned
 | 
| 94 | #
 | 
| 95 | 
 | 
| 96 | 
 | 
| 97 | class WithDict(object):
 | 
| 98 | 
 | 
| 99 |     def __init__(self):
 | 
| 100 |         # type: () -> None
 | 
| 101 |         self.s = 'foo'
 | 
| 102 |         self.d = {}  # type: Dict[str, str]
 | 
| 103 | 
 | 
| 104 | 
 | 
| 105 | #
 | 
| 106 | # Regression for printf bug -- Tag::Opaque
 | 
| 107 | #
 | 
| 108 | 
 | 
| 109 | 
 | 
| 110 | class _Builtin(object):
 | 
| 111 | 
 | 
| 112 |     def __init__(self):
 | 
| 113 |         # type: () -> None
 | 
| 114 |         pass
 | 
| 115 | 
 | 
| 116 |     def Run(self):
 | 
| 117 |         # type: () -> None
 | 
| 118 |         print('_Builtin')
 | 
| 119 | 
 | 
| 120 | 
 | 
| 121 | class Printf(_Builtin):
 | 
| 122 | 
 | 
| 123 |     def __init__(self):
 | 
| 124 |         # type: () -> None
 | 
| 125 |         _Builtin.__init__(self)
 | 
| 126 |         self.cache = {}  # type: Dict[str, str]
 | 
| 127 | 
 | 
| 128 |     def Run(self):
 | 
| 129 |         # type: () -> None
 | 
| 130 |         print('Printf')
 | 
| 131 | 
 | 
| 132 | 
 | 
| 133 | def run_tests():
 | 
| 134 |     # type: () -> None
 | 
| 135 | 
 | 
| 136 |     o1 = Opaque()
 | 
| 137 |     o2 = OpaqueBase()
 | 
| 138 |     o3 = OpaqueDerived()
 | 
| 139 | 
 | 
| 140 |     p1 = Pointers()
 | 
| 141 |     p2 = PointersBase()
 | 
| 142 |     p3 = PointersDerived()
 | 
| 143 | 
 | 
| 144 |     m1 = BaseWithMethod()
 | 
| 145 |     m2 = DerivedWithMethod()
 | 
| 146 | 
 | 
| 147 |     # Reproduce bug found in osh_eval with IfsSplitter and the dict splitter
 | 
| 148 | 
 | 
| 149 |     c = WithDict()
 | 
| 150 |     c.d['key'] = 'value'
 | 
| 151 | 
 | 
| 152 |     mylib.MaybeCollect()
 | 
| 153 | 
 | 
| 154 |     s = 'heap'
 | 
| 155 |     p1.s = s[1:]  # why do we need this to trigger the bug
 | 
| 156 |     # Does not trigger it
 | 
| 157 |     #p1.s = s
 | 
| 158 | 
 | 
| 159 |     #p1.t = s[2:]
 | 
| 160 |     print(c.d['key'])
 | 
| 161 | 
 | 
| 162 |     # Reproduce printf bug
 | 
| 163 |     p = Printf()
 | 
| 164 |     mylib.MaybeCollect()
 | 
| 165 | 
 | 
| 166 |     log("cache length %d", len(p.cache))
 | 
| 167 | 
 | 
| 168 | 
 | 
| 169 | def run_benchmarks():
 | 
| 170 |     # type: () -> None
 | 
| 171 | 
 | 
| 172 |     # Use some memory to test the size of these objects
 | 
| 173 | 
 | 
| 174 |     op = []  # type: List[OpaqueBase]
 | 
| 175 |     p = []  # type: List[PointersBase]
 | 
| 176 |     m = []  # type: List[BaseWithMethod]
 | 
| 177 | 
 | 
| 178 |     for i in xrange(1000):
 | 
| 179 |         o1 = Opaque()
 | 
| 180 |         o2 = OpaqueBase()
 | 
| 181 |         o3 = OpaqueDerived()
 | 
| 182 | 
 | 
| 183 |         op.append(o2)
 | 
| 184 |         op.append(o3)
 | 
| 185 | 
 | 
| 186 |         p1 = Pointers()
 | 
| 187 | 
 | 
| 188 |         p2 = PointersBase()
 | 
| 189 |         p3 = PointersDerived()
 | 
| 190 | 
 | 
| 191 |         p.append(p2)
 | 
| 192 |         p.append(p3)
 | 
| 193 | 
 | 
| 194 |         m1 = BaseWithMethod()
 | 
| 195 |         m2 = DerivedWithMethod()
 | 
| 196 | 
 | 
| 197 |         m.append(m1)
 | 
| 198 |         m.append(m2)
 | 
| 199 | 
 | 
| 200 |         mylib.MaybeCollect()
 | 
| 201 | 
 | 
| 202 |     log('len(op) = %d', len(op))
 | 
| 203 |     log('len(p) = %d', len(p))
 | 
| 204 |     log('len(m) = %d', len(m))
 | 
| 205 | 
 | 
| 206 | 
 | 
| 207 | if __name__ == '__main__':
 | 
| 208 |     if os.getenv('BENCHMARK'):
 | 
| 209 |         log('Benchmarking...')
 | 
| 210 |         run_benchmarks()
 | 
| 211 |     else:
 | 
| 212 |         run_tests()
 |