Source

pypy / pypy / rpython / rweakref.py

import weakref
from pypy.annotation import model as annmodel
from pypy.objspace.flow.model import Constant
from pypy.rpython.error import TyperError
from pypy.rpython.rmodel import Repr
from pypy.rpython.rclass import getinstancerepr
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.ootypesystem import ootype

# ____________________________________________________________
#
# RTyping of RPython-level weakrefs

class __extend__(annmodel.SomeWeakRef):
    def rtyper_makerepr(self, rtyper):
        if rtyper.type_system.name == 'lltypesystem':
            return LLWeakRefRepr(rtyper)
        else:
            return OOWeakRefRepr(rtyper)
    def rtyper_makekey(self):
        return self.__class__,

class BaseWeakRefRepr(Repr):

    def __init__(self, rtyper):
        self.rtyper = rtyper
        if not rtyper.getconfig().translation.rweakref:
            raise TyperError("RPython-level weakrefs are not supported by "
                             "this backend or GC policy")

    def convert_const(self, value):
        if value is None:
            return self.null_wref

        assert isinstance(value, weakref.ReferenceType)
        instance = value()
        bk = self.rtyper.annotator.bookkeeper
        # obscure!  if the annotator hasn't seen this object before,
        # we don't want to look at it now (confusion tends to result).
        if instance is None or not bk.have_seen(instance):
            return self.dead_wref
        else:
            repr = self.rtyper.bindingrepr(Constant(instance))
            llinstance = repr.convert_const(instance)
            return self._weakref_create(llinstance)

    def _weakref_create(self, llinstance):
        raise NotImplementedError

class LLWeakRefRepr(BaseWeakRefRepr):
    lowleveltype = llmemory.WeakRefPtr
    dead_wref = llmemory.dead_wref
    null_wref = lltype.nullptr(llmemory.WeakRef)

    def rtype_simple_call(self, hop):
        v_wref, = hop.inputargs(self)
        hop.exception_cannot_occur()
        if hop.r_result.lowleveltype is lltype.Void: # known-to-be-dead weakref
            return hop.inputconst(lltype.Void, None)
        else:
            return hop.genop('weakref_deref', [v_wref],
                             resulttype=hop.r_result)

    def _weakref_create(self, llinstance):
        return llmemory.weakref_create(llinstance)

class OOWeakRefRepr(BaseWeakRefRepr):
    lowleveltype = ootype.WeakReference
    dead_wref = ootype.dead_wref
    null_wref = ootype.null(ootype.WeakReference)
    
    def rtype_simple_call(self, hop):
        v_wref, = hop.inputargs(self)
        cname = hop.inputconst(ootype.Void, 'll_deref')
        hop.exception_cannot_occur()
        if hop.r_result.lowleveltype is lltype.Void: # known-to-be-dead weakref
            return hop.inputconst(lltype.Void, None)
        else:
            v_deref = hop.genop('oosend', [cname, v_wref],
                                resulttype=ootype.ROOT)
            return hop.genop('oodowncast', [v_deref], resulttype=hop.r_result)

    def _weakref_create(self, llinstance):
        return ootype.ooweakref_create(llinstance)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.