Commits

Maciej Fijalkowski committed c4813b2

(arigo, fijal)
Rename _freeze_ returning False to _cleanup_, now we can have
hasattr(x, '_freeze_') without strange hacks to check for frozen PBCs.

Comments (0)

Files changed (28)

pypy/annotation/bookkeeper.py

         self.descs = {}          # map Python objects to their XxxDesc wrappers
         self.methoddescs = {}    # map (funcdesc, classdef) to the MethodDesc
         self.classdefs = []      # list of all ClassDefs
-        self.pbctypes = {}
         self.seen_mutable = {}
         self.listdefs = {}       # map position_keys to ListDefs
         self.dictdefs = {}       # map position_keys to DictDefs
                 result = None
             if result is None:
                 result = SomePBC([self.getdesc(x)])
-        elif hasattr(x, '_freeze_') and x._freeze_():
+        elif hasattr(x, '_freeze_'):
+            assert x._freeze_() is True
             # user-defined classes can define a method _freeze_(), which
             # is called when a prebuilt instance is found.  If the method
             # returns True, the instance is considered immutable and becomes
             result = SomePBC([self.getdesc(x)])
         elif hasattr(x, '__class__') \
                  and x.__class__.__module__ != '__builtin__':
+            if hasattr(x, '_cleanup_'):
+                x._cleanup_()
             self.see_mutable(x)
             result = SomeInstance(self.getuniqueclassdef(x.__class__))
         elif x is None:
             elif isinstance(pyobj, types.MethodType):
                 if pyobj.im_self is None:   # unbound
                     return self.getdesc(pyobj.im_func)
-                elif (hasattr(pyobj.im_self, '_freeze_') and
-                      pyobj.im_self._freeze_()):  # method of frozen
+                if hasattr(pyobj.im_self, '_cleanup_'):
+                    pyobj.im_self._cleanup_()
+                if hasattr(pyobj.im_self, '_freeze_'):  # method of frozen
+                    assert pyobj.im_self._freeze_() is True
                     result = description.MethodOfFrozenDesc(self,
                         self.getdesc(pyobj.im_func),            # funcdesc
                         self.getdesc(pyobj.im_self))            # frozendesc
                         name)
             else:
                 # must be a frozen pre-built constant, but let's check
-                try:
-                    assert pyobj._freeze_()
-                except AttributeError:
+                if hasattr(pyobj, '_freeze_'):
+                    assert pyobj._freeze_() is True
+                else:
                     if hasattr(pyobj, '__call__'):
                         msg = "object with a __call__ is not RPython"
                     else:
             return False
         
     def getfrozen(self, pyobj):
-        result = description.FrozenDesc(self, pyobj)
-        cls = result.knowntype
-        if cls not in self.pbctypes:
-            self.pbctypes[cls] = True
-        return result
+        return description.FrozenDesc(self, pyobj)
 
     def getmethoddesc(self, funcdesc, originclassdef, selfclassdef, name,
                       flags={}):

pypy/annotation/builtin.py

         for variable in variables:
             assert bk.annotator.binding(variable) == s_obj
         r.knowntypedata = {}
-        if isinstance(s_obj, SomeInstance) and isinstance(s_type, SomePBC):
+        
+        if not hasattr(typ, '_freeze_') and isinstance(s_type, SomePBC):
             add_knowntypedata(r.knowntypedata, True, variables, bk.valueoftype(typ))
     return r
 

pypy/annotation/signature.py

     elif bookkeeper and extregistry.is_registered_type(t, bookkeeper.policy):
         entry = extregistry.lookup_type(t, bookkeeper.policy)
         return entry.compute_annotation_bk(bookkeeper)
-    elif bookkeeper and t.__module__ != '__builtin__' and t not in bookkeeper.pbctypes:
+    elif t is type:
+        return SomeType()
+    elif bookkeeper and not hasattr(t, '_freeze_'):
         classdef = bookkeeper.getuniqueclassdef(t)
         return SomeInstance(classdef)
-    elif t is type:
-        return SomeType()
     else:
         raise AssertionError("annotationoftype(%r)" % (t,))
 

pypy/annotation/test/test_annrpython.py

 
     def test_freeze_protocol(self):
         class Stuff:
-            def __init__(self, flag):
+            def __init__(self):
                 self.called = False
-                self.flag = flag
             def _freeze_(self):
                 self.called = True
-                return self.flag
-        myobj = Stuff(True)
+                return True
+        myobj = Stuff()
         a = self.RPythonAnnotator()
         s = a.build_types(lambda: myobj, [])
         assert myobj.called
         assert isinstance(s, annmodel.SomePBC)
         assert s.const == myobj
-        myobj = Stuff(False)
+
+    def test_cleanup_protocol(self): 
+        class Stuff:
+            def __init__(self):
+                self.called = False
+            def _cleanup_(self):
+                self.called = True
+        myobj = Stuff()
         a = self.RPythonAnnotator()
         s = a.build_types(lambda: myobj, [])
         assert myobj.called

pypy/interpreter/function.py

     # delicate
     _all = {'': None}
 
-    def _freeze_(self):
+    def _cleanup_(self):
         from pypy.interpreter.gateway import BuiltinCode
         if isinstance(self.code, BuiltinCode):
             # we have been seen by other means so rtyping should not choke

pypy/interpreter/mixedmodule.py

             self.w_initialdict = space.call_method(self.w_dict, 'items')
         return self.w_dict
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self.getdict(self.space)
         self.w_initialdict = None
         self.startup_called = False
         self._frozen = True
-        # hint for the annotator: Modules can hold state, so they are
-        # not constant
-        return False
 
     def buildloaders(cls):
         """ NOT_RPYTHON """

pypy/interpreter/test/test_appinterp.py

         # Uncomment this line for a workaround
         # space.getattr(w_ssl, space.wrap('SSLError'))
 
-        w_socket._freeze_()
+        w_socket._cleanup_()
         assert w_socket.startup_called == False
-        w_ssl._freeze_() # w_ssl.appleveldefs['SSLError'] imports _socket
+        w_ssl._cleanup_() # w_ssl.appleveldefs['SSLError'] imports _socket
         assert w_socket.startup_called == False
 

pypy/jit/backend/llgraph/runner.py

         self._future_values = []
         self._descrs = {}
 
-    def _freeze_(self):
+    def _cleanup_(self):
         assert self.translate_support_code
-        return False
 
     def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
                  arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):

pypy/jit/metainterp/blackhole.py

         self.setup_descrs(asm.descrs)
         self.metainterp_sd = metainterp_sd
         self.num_interpreters = 0
-        self._freeze_()
+        self._cleanup_()
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self.blackholeinterps = []
-        return False
 
     def setup_insns(self, insns):
         assert len(insns) <= 256, "too many instructions!"

pypy/module/_codecs/interp_codecs.py

             self.unicodedata_handler = UnicodeData_Handler(space, w_getcode)
             return self.unicodedata_handler
 
-    def _freeze_(self):
+    def _cleanup_(self):
         assert not self.codec_search_path
-        return False
 
 def register_codec(space, w_search_function):
     """register(search_function)

pypy/module/_file/interp_stream.py

                                  self.space.wrap("stream lock is not held"))
         self._release_lock()
 
-    def _freeze_(self):
+    def _cleanup_(self):
         # remove the lock object, which will be created again as needed at
         # run-time.
         self.slock = None
         assert self.slockowner is None
-        return False
 
     def stream_read(self, n):
         """

pypy/module/_multiprocessing/interp_semaphore.py

     def __init__(self, space):
         self.counter = 0
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self.counter = 0
 
     def getCount(self):

pypy/module/cpyext/pyobject.py

         # For tests
         self.non_heaptypes_w = []
 
-    def _freeze_(self):
+    def _cleanup_(self):
         assert self.borrow_mapping == {None: {}}
         self.py_objects_r2w.clear() # is not valid anymore after translation
-        return False
 
     def init_r2w_from_w2r(self):
         """Rebuilds the dict py_objects_r2w on startup"""

pypy/module/pypyjit/interp_jit.py

         PyCode__initialize(self)
         self.jit_cells = {}
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self.jit_cells = {}
-        return False
 
 # ____________________________________________________________
 #

pypy/module/rctime/interp_time.py

         def __init__(self, space):
             self.main_thread = 0
 
-        def _freeze_(self):
+        def _cleanup_(self):
             self.main_thread = 0
             globalState.init()
 

pypy/module/thread/gil.py

 
 class SpaceState:
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self.action_after_thread_switch = None
         # ^^^ set by AsyncAction.fire_after_thread_switch()
-        return False
 
     def after_thread_switch(self):
         # this is support logic for the signal module, to help it deliver
             action.fire()
 
 spacestate = SpaceState()
-spacestate._freeze_()
+spacestate._cleanup_()
 
 # Fragile code below.  We have to preserve the C-level errno manually...
 

pypy/module/thread/os_thread.py

         bootstrapper.w_callable = None
         bootstrapper.args = None
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self.reinit()
-        return False
 
     def bootstrap():
         # Note that when this runs, we already hold the GIL.  This is ensured

pypy/module/thread/test/test_ll_thread.py

     # In this module, we assume that ll_thread.start_new_thread() is not
     # providing us with a GIL equivalent, except in test_gc_locking
     # which installs its own aroundstate.
-    rffi.aroundstate._freeze_()
+    rffi.aroundstate._cleanup_()
 
 def test_lock():
     l = allocate_lock()
         try:
             fn = self.getcompiled(f, [])
         finally:
-            rffi.aroundstate._freeze_()
+            rffi.aroundstate._cleanup_()
         answers = fn()
         assert answers == expected
 

pypy/module/thread/threadlocals.py

 
     def __init__(self):
         self._valuedict = {}   # {thread_ident: ExecutionContext()}
-        self._freeze_()
+        self._cleanup_()
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self._valuedict.clear()
         self._mainthreadident = 0
         self._mostrecentkey = 0        # fast minicaching for the common case
         self._mostrecentvalue = None   # fast minicaching for the common case
-        return False
 
     def getvalue(self):
         ident = thread.get_ident()

pypy/objspace/flow/objspace.py

         if (not isinstance(to_check, (type, types.ClassType, types.ModuleType)) and
             # classes/types/modules are assumed immutable
             hasattr(to_check, '__class__') and to_check.__class__.__module__ != '__builtin__'):
-            frozen = hasattr(to_check, '_freeze_') and to_check._freeze_()
-            if not frozen:
+            frozen = hasattr(to_check, '_freeze_')
+            if frozen:
+                assert to_check._freeze_() is True
+            else:
                 # cannot count on it not mutating at runtime!
                 raise UnwrapException
         return obj

pypy/objspace/std/typeobject.py

 
     def deldictvalue(w_self, space, key):
         if w_self.lazyloaders:
-            w_self._freeze_()    # force un-lazification
+            w_self._cleanup_()    # force un-lazification
         if (not space.config.objspace.std.mutable_builtintypes
                 and not w_self.is_heaptype()):
             msg = "can't delete attributes on type object '%s'"
                 w_self.name, w_subtype.name, w_subtype.name)
         return w_subtype
 
-    def _freeze_(w_self):
+    def _cleanup_(w_self):
         "NOT_RPYTHON.  Forces the lazy attributes to be computed."
         if 'lazyloaders' in w_self.__dict__:
             for attr in w_self.lazyloaders.keys():
                 w_self.getdictvalue(w_self.space, attr)
             del w_self.lazyloaders
-        return False
 
     def getdict(w_self, space): # returning a dict-proxy!
         from pypy.objspace.std.dictproxyobject import DictProxyStrategy
         from pypy.objspace.std.dictmultiobject import W_DictMultiObject
         if w_self.lazyloaders:
-            w_self._freeze_()    # force un-lazification
+            w_self._cleanup_()    # force un-lazification
         strategy = space.fromcache(DictProxyStrategy)
         storage = strategy.erase(w_self)
         return W_DictMultiObject(space, strategy, storage)
                     elif (hasattr(value, '__class__')
                           and value.__class__.__module__ != '__builtin__'):
                         if hasattr(value, '_freeze_'):
-                            continue   # value._freeze_() is better not called
+                            kind = "1:INT"
                         elif getattr(value, '_alloc_flavor_', 'gc') == 'gc':
                             kind = '2:REF'
                         else:
         return False      # don't keep any type
     if isinstance(x, (list, dict, str)):
         return True       # keep lists and dicts and strings
-    try:
-        return not x._freeze_()   # don't keep any frozen object
-    except AttributeError:
-        return type(x).__module__ != '__builtin__'   # keep non-builtins
-    except Exception:
-        return False      # don't keep objects whose _freeze_() method explodes
+    if hasattr(x, '_freeze_'):
+        return False
+    return type(x).__module__ != '__builtin__'   # keep non-builtins
 
 def add_memory_pressure(estimate):
     """Add memory pressure for OpaquePtrs."""

pypy/rlib/rope.py

     def __add__(self, other):
         return concatenate(self, other)
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self.additional_info()
 
 class LiteralNode(StringNode):

pypy/rlib/rstacklet.py

     def __init__(self):
         self.sthread = None
         self.active = []
-    def _freeze_(self):
+    def _cleanup_(self):
         self.__init__()
-        return False
     def add(self, h):
         if not self.sthread.is_empty_handle(h):
             if h == self.sthread.get_null_handle():

pypy/rlib/timer.py

         self.levels = {}
         self.timingorder = []
 
-    def _freeze_(self):
+    def _cleanup_(self):
         self.reset()
 
     def start(self, timer):

pypy/rpython/lltypesystem/llarena.py

     class LinuxPageSize:
         def __init__(self):
             self.pagesize = 0
-        _freeze_ = __init__
+        def _cleanup_(self):
+            self.pagesize = 0
     linuxpagesize = LinuxPageSize()
 
     def clear_large_memory_chunk(baseaddr, size):

pypy/rpython/lltypesystem/rffi.py

 
 AroundFnPtr = lltype.Ptr(lltype.FuncType([], lltype.Void))
 class AroundState:
-    def _freeze_(self):
+    def _cleanup_(self):
         self.before = None    # or a regular RPython function
         self.after = None     # or a regular RPython function
-        return False
 aroundstate = AroundState()
-aroundstate._freeze_()
+aroundstate._cleanup_()
 
 class StackCounter:
-    def _freeze_(self):
+    def _cleanup_(self):
         self.stacks_counter = 1     # number of "stack pieces": callbacks
-        return False                # and threads increase it by one
+                                    # and threads increase it by one
 stackcounter = StackCounter()
-stackcounter._freeze_()
+stackcounter._cleanup_()
 
 def llexternal_use_eci(compilation_info):
     """Return a dummy function that, if called in a RPython program,