[pypy-svn] r53596 - in pypy/dist/pypy: rlib rpython rpython/lltypesystem rpython/memory rpython/memory/gc rpython/memory/gctransform rpython/memory/test translator/c translator/c/src translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Tue Apr 8 22:48:28 CEST 2008
Author: arigo
Date: Tue Apr 8 22:48:25 2008
New Revision: 53596
Modified:
pypy/dist/pypy/rlib/rgc.py
pypy/dist/pypy/rpython/llinterp.py
pypy/dist/pypy/rpython/lltypesystem/llheap.py
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
pypy/dist/pypy/rpython/memory/gc/base.py
pypy/dist/pypy/rpython/memory/gc/semispace.py
pypy/dist/pypy/rpython/memory/gctransform/framework.py
pypy/dist/pypy/rpython/memory/gcwrapper.py
pypy/dist/pypy/rpython/memory/test/snippet.py
pypy/dist/pypy/translator/c/gc.py
pypy/dist/pypy/translator/c/src/mem.h
pypy/dist/pypy/translator/c/test/test_boehm.py
Log:
Add and implement rlib.rgc.{disable,enable}_finalizers().
Modified: pypy/dist/pypy/rlib/rgc.py
==============================================================================
--- pypy/dist/pypy/rlib/rgc.py (original)
+++ pypy/dist/pypy/rlib/rgc.py Tue Apr 8 22:48:25 2008
@@ -11,6 +11,15 @@
"""
pass
+def disable_finalizers():
+ """Prevent __del__ methods from running.
+ Calls to disable_finalizers/enable_finalizers can be nested.
+ """
+ gc.disable() # rough approximation on top of CPython
+
+def enable_finalizers():
+ gc.enable() # rough approximation on top of CPython
+
# ____________________________________________________________
# Framework GC features
@@ -162,3 +171,14 @@
[v_nbytes] = hop.inputargs(lltype.Signed)
return hop.genop('gc_set_max_heap_size', [v_nbytes],
resulttype=lltype.Void)
+
+class CollectEntry(ExtRegistryEntry):
+ _about_ = (disable_finalizers, enable_finalizers)
+
+ def compute_result_annotation(self):
+ from pypy.annotation import model as annmodel
+ return annmodel.s_None
+
+ def specialize_call(self, hop):
+ opname = 'gc__' + self.instance.__name__
+ return hop.genop(opname, [], resulttype=hop.r_result)
Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py (original)
+++ pypy/dist/pypy/rpython/llinterp.py Tue Apr 8 22:48:25 2008
@@ -753,6 +753,12 @@
def op_gc__collect(self):
self.heap.collect()
+ def op_gc__disable_finalizers(self):
+ self.heap.disable_finalizers()
+
+ def op_gc__enable_finalizers(self):
+ self.heap.enable_finalizers()
+
def op_gc_free(self, addr):
# what can you do?
pass
@@ -836,7 +842,7 @@
def op_raw_malloc(self, size):
assert lltype.typeOf(size) == lltype.Signed
- return self.heap.raw_malloc(size)
+ return llmemory.raw_malloc(size)
op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc
@@ -848,20 +854,20 @@
def op_raw_malloc_usage(self, size):
assert lltype.typeOf(size) == lltype.Signed
- return self.heap.raw_malloc_usage(size)
+ return llmemory.raw_malloc_usage(size)
def op_raw_free(self, addr):
checkadr(addr)
- self.heap.raw_free(addr)
+ llmemory.raw_free(addr)
def op_raw_memclear(self, addr, size):
checkadr(addr)
- self.heap.raw_memclear(addr, size)
+ llmemory.raw_memclear(addr, size)
def op_raw_memcopy(self, fromaddr, toaddr, size):
checkadr(fromaddr)
checkadr(toaddr)
- self.heap.raw_memcopy(fromaddr, toaddr, size)
+ llmemory.raw_memcopy(fromaddr, toaddr, size)
def op_raw_load(self, addr, typ, offset):
checkadr(addr)
Modified: pypy/dist/pypy/rpython/lltypesystem/llheap.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llheap.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/llheap.py Tue Apr 8 22:48:25 2008
@@ -1,14 +1,11 @@
# only for the LLInterpreter. Don't use directly.
from pypy.rpython.lltypesystem.lltype import pyobjectptr, malloc, free, typeOf
-from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free
-from pypy.rpython.lltypesystem.llmemory import raw_memclear, raw_memcopy
-from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage, \
- weakref_create, weakref_deref
+from pypy.rpython.lltypesystem.llmemory import weakref_create, weakref_deref
setfield = setattr
from operator import setitem as setarrayitem
-from gc import collect
+from pypy.rlib.rgc import collect, disable_finalizers, enable_finalizers
def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue):
assert typeOf(newvalue) == INNERTYPE
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Tue Apr 8 22:48:25 2008
@@ -387,6 +387,8 @@
# __________ GC operations __________
'gc__collect': LLOp(canunwindgc=True),
+ 'gc__disable_finalizers': LLOp(),
+ 'gc__enable_finalizers': LLOp(canunwindgc=True),
'gc_free': LLOp(),
'gc_fetch_exception': LLOp(),
'gc_restore_exception': LLOp(),
Modified: pypy/dist/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/base.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/base.py Tue Apr 8 22:48:25 2008
@@ -114,6 +114,12 @@
def x_clone(self, clonedata):
raise RuntimeError("no support for x_clone in the GC")
+ def disable_finalizers(self):
+ pass # xxx this should really be implemented by all subclasses
+
+ def enable_finalizers(self):
+ pass # xxx this should really be implemented by all subclasses
+
def trace(self, obj, callback, arg):
"""Enumerate the locations inside the given obj that can contain
GC pointers. For each such location, callback(pointer, arg) is
Modified: pypy/dist/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/semispace.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/semispace.py Tue Apr 8 22:48:25 2008
@@ -524,17 +524,18 @@
self.run_finalizers = new_run_finalizer
def execute_finalizers(self):
- if self.finalizer_lock_count > 0:
- return # the outer invocation of execute_finalizers() will do it
- self.finalizer_lock_count = 1
+ self.finalizer_lock_count += 1
try:
while self.run_finalizers.non_empty():
#print "finalizer"
+ if self.finalizer_lock_count > 1:
+ # the outer invocation of execute_finalizers() will do it
+ break
obj = self.run_finalizers.popleft()
finalizer = self.getfinalizer(self.get_type_id(obj))
finalizer(obj)
finally:
- self.finalizer_lock_count = 0
+ self.finalizer_lock_count -= 1
STATISTICS_NUMBERS = 0
Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Tue Apr 8 22:48:25 2008
@@ -217,6 +217,10 @@
+ [annmodel.SomeBool(), annmodel.SomeBool()], s_gcref)
self.collect_ptr = getfn(GCClass.collect.im_func,
[s_gc], annmodel.s_None)
+ self.disable_finalizers_ptr = getfn(GCClass.disable_finalizers.im_func,
+ [s_gc], annmodel.s_None)
+ self.enable_finalizers_ptr = getfn(GCClass.enable_finalizers.im_func,
+ [s_gc], annmodel.s_None)
# in some GCs we can inline the common case of
# malloc_fixedsize(typeid, size, True, False, False)
@@ -526,6 +530,21 @@
resultvar=op.result)
self.pop_roots(hop, livevars)
+ def gct_gc__disable_finalizers(self, hop):
+ # cannot collect()
+ op = hop.spaceop
+ hop.genop("direct_call", [self.disable_finalizers_ptr,
+ self.c_const_gc],
+ resultvar=op.result)
+
+ def gct_gc__enable_finalizers(self, hop):
+ # can collect() because it typically calls pending finalizers
+ op = hop.spaceop
+ livevars = self.push_roots(hop)
+ hop.genop("direct_call", [self.enable_finalizers_ptr, self.c_const_gc],
+ resultvar=op.result)
+ self.pop_roots(hop, livevars)
+
def gct_gc_x_swap_pool(self, hop):
op = hop.spaceop
[v_malloced] = op.args
Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py Tue Apr 8 22:48:25 2008
@@ -81,6 +81,12 @@
def collect(self):
self.gc.collect()
+ def disable_finalizers(self):
+ self.gc.disable_finalizers()
+
+ def enable_finalizers(self):
+ self.gc.enable_finalizers()
+
def weakref_create_getlazy(self, objgetter):
# we have to be lazy in reading the llinterp variable containing
# the 'obj' pointer, because the gc.malloc() call below could
Modified: pypy/dist/pypy/rpython/memory/test/snippet.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/snippet.py (original)
+++ pypy/dist/pypy/rpython/memory/test/snippet.py Tue Apr 8 22:48:25 2008
@@ -1,9 +1,15 @@
+import os
+from pypy.tool.udir import udir
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.lltypesystem.lloperation import llop
class SemiSpaceGCTests:
large_tests_ok = False
+ def run_ok(self, f):
+ res = self.run(f)
+ assert res == 'ok'
+
def test_finalizer_order(self):
import random
from pypy.tool.algo import graphlib
@@ -119,3 +125,53 @@
print summary
print msg
py.test.fail(msg)
+
+ def test_disable_finalizers(self):
+ from pypy.rlib import rgc
+ if self.large_tests_ok:
+ MULTIPLY = 50
+ else:
+ MULTIPLY = 1
+
+ tmpfilepath = udir.join('test_disable_finalizers')
+
+ class State:
+ pass
+ state = State()
+ state.tmpfilename = str(tmpfilepath)
+ state.fd = -1
+
+ class X(object):
+ def __init__(self, x):
+ self.x = str(x)
+ def __del__(self):
+ if state.fd >= 0:
+ os.write(state.fd, self.x)
+
+ def do_stuff():
+ lst = [X(n) for n in range(7*MULTIPLY)]
+ return len(lst)
+
+ def f():
+ fd = os.open(state.tmpfilename,
+ os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
+ 0644)
+ state.fd = fd
+ for i in range(10*MULTIPLY):
+ do_stuff()
+ rgc.disable_finalizers()
+ os.write(fd, '-')
+ do_stuff()
+ os.write(fd, '+')
+ rgc.enable_finalizers()
+ state.fd = -1
+ os.close(fd)
+ return 'ok'
+
+ self.run_ok(f)
+ buf = tmpfilepath.read()
+ assert buf.count('-') == buf.count('+')
+ assert buf.count('-') + buf.count('+') < len(buf)
+ for i in range(len(buf)):
+ if buf[i] == '-':
+ assert buf[i+1] == '+'
Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py (original)
+++ pypy/dist/pypy/translator/c/gc.py Tue Apr 8 22:48:25 2008
@@ -134,6 +134,12 @@
def OP_GC__COLLECT(self, funcgen, op):
return ''
+ def OP_GC__DISABLE_FINALIZERS(self, funcgen, op):
+ return ''
+
+ def OP_GC__ENABLE_FINALIZERS(self, funcgen, op):
+ return ''
+
class RefcountingRuntimeTypeInfo_OpaqueNode(ContainerNode):
nodekind = 'refcnt rtti'
Modified: pypy/dist/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/mem.h (original)
+++ pypy/dist/pypy/translator/c/src/mem.h Tue Apr 8 22:48:25 2008
@@ -131,20 +131,29 @@
else \
GC_GENERAL_REGISTER_DISAPPEARING_LINK(link, obj)
+extern int boehm_gc_finalizer_lock;
void boehm_gc_startup_code(void);
+void boehm_gc_finalizer_notifier(void);
+
+#define OP_GC__DISABLE_FINALIZERS(r) boehm_gc_finalizer_lock++
+#define OP_GC__ENABLE_FINALIZERS(r) (boehm_gc_finalizer_lock--, \
+ boehm_gc_finalizer_notifier())
#ifndef PYPY_NOT_MAIN_FILE
-static void boehm_gc_finalizer_notifier(void)
+int boehm_gc_finalizer_lock = 0;
+void boehm_gc_finalizer_notifier(void)
{
- static int recursing = 0;
- if (recursing)
- return; /* GC_invoke_finalizers() will be done by the
- boehm_gc_finalizer_notifier() that is
- currently in the C stack, when we return there */
- recursing = 1;
- while (GC_should_invoke_finalizers())
+ boehm_gc_finalizer_lock++;
+ while (GC_should_invoke_finalizers()) {
+ if (boehm_gc_finalizer_lock > 1) {
+ /* GC_invoke_finalizers() will be done by the
+ boehm_gc_finalizer_notifier() that is
+ currently in the C stack, when we return there */
+ break;
+ }
GC_invoke_finalizers();
- recursing = 0;
+ }
+ boehm_gc_finalizer_lock--;
}
void boehm_gc_startup_code(void)
{
Modified: pypy/dist/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_boehm.py (original)
+++ pypy/dist/pypy/translator/c/test/test_boehm.py Tue Apr 8 22:48:25 2008
@@ -1,6 +1,7 @@
import py
from pypy.translator.translator import TranslationContext
from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.memory.test import snippet
from pypy.translator.tool.cbuild import check_boehm_presence
from pypy.translator.c.genc import CExtModuleBuilder
from pypy import conftest
@@ -365,3 +366,16 @@
c_fn = self.getcompiled(fn, [int])
res = c_fn(10000)
assert res == 0
+
+ # reusing some tests from pypy.rpython.memory.test.snippet
+ large_tests_ok = True
+
+ def run_ok(self, f):
+ def wrapper():
+ return int(f() == 'ok')
+ c_fn = self.getcompiled(wrapper, [])
+ res = c_fn()
+ assert res == 1
+
+ test_disable_finalizers = (
+ snippet.SemiSpaceGCTests.test_disable_finalizers.im_func)
More information about the Pypy-commit
mailing list