[pypy-commit] pypy remove-objspace-options: Now, if an RPython program uses weakrefs when translation.rweakref is
arigo
pypy.commits at gmail.com
Mon Apr 25 06:33:05 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: remove-objspace-options
Changeset: r83855:0713002caf76
Date: 2016-04-25 12:31 +0200
http://bitbucket.org/pypy/pypy/changeset/0713002caf76/
Log: Now, if an RPython program uses weakrefs when translation.rweakref
is False, we don't get a translation crash; instead we get non-weak
references.
diff --git a/rpython/memory/gctransform/boehm.py b/rpython/memory/gctransform/boehm.py
--- a/rpython/memory/gctransform/boehm.py
+++ b/rpython/memory/gctransform/boehm.py
@@ -46,11 +46,12 @@
ll_malloc_varsize_no_length, [lltype.Signed]*3, llmemory.Address, inline=False)
self.malloc_varsize_ptr = self.inittime_helper(
ll_malloc_varsize, [lltype.Signed]*4, llmemory.Address, inline=False)
- self.weakref_create_ptr = self.inittime_helper(
- ll_weakref_create, [llmemory.Address], llmemory.WeakRefPtr,
- inline=False)
- self.weakref_deref_ptr = self.inittime_helper(
- ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
+ if self.translator.config.translation.rweakref:
+ self.weakref_create_ptr = self.inittime_helper(
+ ll_weakref_create, [llmemory.Address], llmemory.WeakRefPtr,
+ inline=False)
+ self.weakref_deref_ptr = self.inittime_helper(
+ ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
self.identityhash_ptr = self.inittime_helper(
ll_identityhash, [llmemory.Address], lltype.Signed,
inline=False)
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -236,8 +236,9 @@
annmodel.s_None)
self.annotate_walker_functions(getfn)
- self.weakref_deref_ptr = self.inittime_helper(
- ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
+ if translator.config.translation.rweakref:
+ self.weakref_deref_ptr = self.inittime_helper(
+ ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
classdef = bk.getuniqueclassdef(GCClass)
s_gc = annmodel.SomeInstance(classdef)
diff --git a/rpython/rlib/rweakref.py b/rpython/rlib/rweakref.py
--- a/rpython/rlib/rweakref.py
+++ b/rpython/rlib/rweakref.py
@@ -7,7 +7,14 @@
import weakref
from rpython.annotator.model import UnionError
-ref = weakref.ref # basic regular weakrefs are supported in RPython
+
+# Basic regular weakrefs are supported in RPython.
+# Note that if 'translation.rweakref' is False, they will
+# still work, but be implemented as a strong reference.
+# This case is useful for developing new GCs, for example.
+
+ref = weakref.ref
+
def has_weakref_support():
return True # returns False if --no-translation-rweakref
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -782,17 +782,21 @@
def op_weakref_create(self, v_obj):
def objgetter(): # special support for gcwrapper.py
return self.getval(v_obj)
+ assert self.llinterpreter.typer.getconfig().translation.rweakref
return self.heap.weakref_create_getlazy(objgetter)
op_weakref_create.specialform = True
def op_weakref_deref(self, PTRTYPE, obj):
+ assert self.llinterpreter.typer.getconfig().translation.rweakref
return self.heap.weakref_deref(PTRTYPE, obj)
op_weakref_deref.need_result_type = True
def op_cast_ptr_to_weakrefptr(self, obj):
+ assert self.llinterpreter.typer.getconfig().translation.rweakref
return llmemory.cast_ptr_to_weakrefptr(obj)
def op_cast_weakrefptr_to_ptr(self, PTRTYPE, obj):
+ assert self.llinterpreter.typer.getconfig().translation.rweakref
return llmemory.cast_weakrefptr_to_ptr(PTRTYPE, obj)
op_cast_weakrefptr_to_ptr.need_result_type = True
diff --git a/rpython/rtyper/rbuiltin.py b/rpython/rtyper/rbuiltin.py
--- a/rpython/rtyper/rbuiltin.py
+++ b/rpython/rtyper/rbuiltin.py
@@ -735,12 +735,21 @@
@typer_for(llmemory.weakref_create)
@typer_for(weakref.ref)
def rtype_weakref_create(hop):
- vlist = hop.inputargs(hop.args_r[0])
+ from rpython.rtyper.rweakref import BaseWeakRefRepr
+
+ v_inst, = hop.inputargs(hop.args_r[0])
hop.exception_cannot_occur()
- return hop.genop('weakref_create', vlist, resulttype=llmemory.WeakRefPtr)
+ if isinstance(hop.r_result, BaseWeakRefRepr):
+ return hop.r_result._weakref_create(hop, v_inst)
+ else:
+ # low-level <PtrRepr * WeakRef>
+ assert hop.rtyper.getconfig().translation.rweakref
+ return hop.genop('weakref_create', [v_inst],
+ resulttype=llmemory.WeakRefPtr)
@typer_for(llmemory.weakref_deref)
def rtype_weakref_deref(hop):
+ assert hop.rtyper.getconfig().translation.rweakref
c_ptrtype, v_wref = hop.inputargs(lltype.Void, hop.args_r[1])
assert v_wref.concretetype == llmemory.WeakRefPtr
hop.exception_cannot_occur()
@@ -748,6 +757,7 @@
@typer_for(llmemory.cast_ptr_to_weakrefptr)
def rtype_cast_ptr_to_weakrefptr(hop):
+ assert hop.rtyper.getconfig().translation.rweakref
vlist = hop.inputargs(hop.args_r[0])
hop.exception_cannot_occur()
return hop.genop('cast_ptr_to_weakrefptr', vlist,
@@ -755,6 +765,7 @@
@typer_for(llmemory.cast_weakrefptr_to_ptr)
def rtype_cast_weakrefptr_to_ptr(hop):
+ assert hop.rtyper.getconfig().translation.rweakref
c_ptrtype, v_wref = hop.inputargs(lltype.Void, hop.args_r[1])
assert v_wref.concretetype == llmemory.WeakRefPtr
hop.exception_cannot_occur()
diff --git a/rpython/rtyper/rweakref.py b/rpython/rtyper/rweakref.py
--- a/rpython/rtyper/rweakref.py
+++ b/rpython/rtyper/rweakref.py
@@ -11,25 +11,22 @@
class __extend__(annmodel.SomeWeakRef):
def rtyper_makerepr(self, rtyper):
- return WeakRefRepr(rtyper)
+ if rtyper.getconfig().translation.rweakref:
+ return WeakRefRepr(rtyper)
+ else:
+ return EmulatedWeakRefRepr(rtyper)
def rtyper_makekey(self):
return self.__class__,
-class WeakRefRepr(Repr):
- lowleveltype = llmemory.WeakRefPtr
- dead_wref = llmemory.dead_wref
- null_wref = lltype.nullptr(llmemory.WeakRef)
+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
+ return lltype.nullptr(self.lowleveltype.TO)
assert isinstance(value, weakref.ReferenceType)
instance = value()
@@ -39,8 +36,7 @@
else:
repr = self.rtyper.bindingrepr(Constant(instance))
llinstance = repr.convert_const(instance)
- return self._weakref_create(llinstance)
-
+ return self.do_weakref_create(llinstance)
def rtype_simple_call(self, hop):
v_wref, = hop.inputargs(self)
@@ -48,8 +44,53 @@
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)
+ assert v_wref.concretetype == self.lowleveltype
+ return self._weakref_deref(hop, v_wref)
- def _weakref_create(self, llinstance):
+
+class WeakRefRepr(BaseWeakRefRepr):
+ lowleveltype = llmemory.WeakRefPtr
+ dead_wref = llmemory.dead_wref
+
+ def do_weakref_create(self, llinstance):
return llmemory.weakref_create(llinstance)
+
+ def _weakref_create(self, hop, v_inst):
+ return hop.genop('weakref_create', [v_inst],
+ resulttype=llmemory.WeakRefPtr)
+
+ def _weakref_deref(self, hop, v_wref):
+ return hop.genop('weakref_deref', [v_wref],
+ resulttype=hop.r_result)
+
+
+class EmulatedWeakRefRepr(BaseWeakRefRepr):
+ """For the case rweakref=False, we emulate RPython-level weakrefs
+ with regular strong references (but not low-level weakrefs).
+ """
+ lowleveltype = lltype.Ptr(lltype.GcStruct('EmulatedWeakRef',
+ ('ref', llmemory.GCREF)))
+ dead_wref = lltype.malloc(lowleveltype.TO, immortal=True, zero=True)
+
+ def do_weakref_create(self, llinstance):
+ p = lltype.malloc(self.lowleveltype.TO, immortal=True)
+ p.ref = lltype.cast_opaque_ptr(llmemory.GCREF, llinstance)
+ return p
+
+ def _weakref_create(self, hop, v_inst):
+ c_type = hop.inputconst(lltype.Void, self.lowleveltype.TO)
+ c_flags = hop.inputconst(lltype.Void, {'flavor': 'gc'})
+ v_ptr = hop.genop('malloc', [c_type, c_flags],
+ resulttype=self.lowleveltype)
+ v_gcref = hop.genop('cast_opaque_ptr', [v_inst],
+ resulttype=llmemory.GCREF)
+ c_ref = hop.inputconst(lltype.Void, 'ref')
+ hop.genop('setfield', [v_ptr, c_ref, v_gcref])
+ return v_ptr
+
+ def _weakref_deref(self, hop, v_wref):
+ c_ref = hop.inputconst(lltype.Void, 'ref')
+ v_gcref = hop.genop('getfield', [v_wref, c_ref],
+ resulttype=llmemory.GCREF)
+ return hop.genop('cast_opaque_ptr', [v_gcref],
+ resulttype=hop.r_result)
diff --git a/rpython/rtyper/test/test_rweakref.py b/rpython/rtyper/test/test_rweakref.py
--- a/rpython/rtyper/test/test_rweakref.py
+++ b/rpython/rtyper/test/test_rweakref.py
@@ -138,3 +138,22 @@
res = self.interpret(f, [])
assert res == lltype.nullptr(S)
+
+
+class TestRWeakrefDisabled(BaseRtypingTest):
+ def test_no_real_weakref(self):
+ class A:
+ pass
+ a1 = A()
+ mylist = [weakref.ref(a1), None]
+ def g():
+ a2 = A()
+ return weakref.ref(a2)
+ def fn(i):
+ w = g()
+ rgc.collect()
+ assert w() is not None
+ return mylist[i] is None
+
+ assert self.interpret(fn, [0], rweakref=False) is False
+ assert self.interpret(fn, [1], rweakref=False) is True
More information about the pypy-commit
mailing list