aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Friedrich Bolz-Tereick <cfbolz@gmx.de>2021-02-01 14:10:13 +0100
committerCarl Friedrich Bolz-Tereick <cfbolz@gmx.de>2021-02-01 14:10:13 +0100
commitdd7373fc460cd9a304c3bef2a3c150c3c2a4dd02 (patch)
treee85853ee6e56601e541842d8bf803621efbd1d3f /rpython/rlib
parentmerge default (diff)
parentmerge heads (diff)
downloadpypy-dd7373fc460cd9a304c3bef2a3c150c3c2a4dd02.tar.gz
pypy-dd7373fc460cd9a304c3bef2a3c150c3c2a4dd02.tar.bz2
pypy-dd7373fc460cd9a304c3bef2a3c150c3c2a4dd02.zip
merge default
Diffstat (limited to 'rpython/rlib')
-rw-r--r--rpython/rlib/objectmodel.py10
-rw-r--r--rpython/rlib/test/test_objectmodel.py37
2 files changed, 46 insertions, 1 deletions
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
index 5faa6850fd..37ccdf9cb1 100644
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -1067,3 +1067,13 @@ def import_from_mixin(M, special_methods=['__init__', '__del__']):
target[key] = value
if immutable_fields:
target['_immutable_fields_'] = target.get('_immutable_fields_', []) + immutable_fields
+
+def never_allocate(cls):
+ """
+ Class decorator to ensure that a class is NEVER instantiated at runtime.
+
+ Useful e.g for context manager which are expected to be constant-folded
+ away.
+ """
+ cls._rpython_never_allocate_ = True
+ return cls
diff --git a/rpython/rlib/test/test_objectmodel.py b/rpython/rlib/test/test_objectmodel.py
index 6bcb9d60c6..5f14528556 100644
--- a/rpython/rlib/test/test_objectmodel.py
+++ b/rpython/rlib/test/test_objectmodel.py
@@ -7,7 +7,8 @@ from rpython.rlib.objectmodel import (
resizelist_hint, is_annotation_constant, always_inline, NOT_CONSTANT,
iterkeys_with_hash, iteritems_with_hash, contains_with_hash,
setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin,
- fetch_translated_config, try_inline, delitem_if_value_is, move_to_end)
+ fetch_translated_config, try_inline, delitem_if_value_is, move_to_end,
+ never_allocate, dont_inline)
from rpython.translator.translator import TranslationContext, graphof
from rpython.rtyper.test.tool import BaseRtypingTest
from rpython.rtyper.test.test_llinterp import interpret
@@ -851,3 +852,37 @@ def test_import_from_mixin_immutable_fields():
import_from_mixin(C)
assert BA._immutable_fields_ == ['c', 'a']
+
+
+def test_never_allocate():
+ from rpython.translator.c.test.test_genc import compile as c_compile
+ from rpython.memory.gctransform.transform import GCTransformError
+
+ @never_allocate
+ class MyClass(object):
+ def __init__(self, x):
+ self.x = x + 1
+
+ @dont_inline
+ def allocate_MyClass(x):
+ return MyClass(x)
+
+ def f(x):
+ # this fails because the allocation of MyClass can't be
+ # constant-folded (because it's inside a @dont_inline function)
+ return allocate_MyClass(x).x
+
+ def g(x):
+ # this works because MyClass is constant folded, so the GC transformer
+ # never sees a malloc(MyClass)
+ return MyClass(x).x
+
+ # test what happens if MyClass escapes
+ with py.test.raises(GCTransformError) as exc:
+ c_compile(f, [int])
+ assert '[function allocate_MyClass]' in str(exc)
+ assert 'was marked as @never_allocate' in str(exc)
+
+ # test that it works in the "normal" case
+ compiled_g = c_compile(g, [int])
+ assert compiled_g(41) == 42