diff options
author | Carl Friedrich Bolz-Tereick <cfbolz@gmx.de> | 2021-02-01 14:10:13 +0100 |
---|---|---|
committer | Carl Friedrich Bolz-Tereick <cfbolz@gmx.de> | 2021-02-01 14:10:13 +0100 |
commit | dd7373fc460cd9a304c3bef2a3c150c3c2a4dd02 (patch) | |
tree | e85853ee6e56601e541842d8bf803621efbd1d3f /rpython/rlib | |
parent | merge default (diff) | |
parent | merge heads (diff) | |
download | pypy-dd7373fc460cd9a304c3bef2a3c150c3c2a4dd02.tar.gz pypy-dd7373fc460cd9a304c3bef2a3c150c3c2a4dd02.tar.bz2 pypy-dd7373fc460cd9a304c3bef2a3c150c3c2a4dd02.zip |
merge default
Diffstat (limited to 'rpython/rlib')
-rw-r--r-- | rpython/rlib/objectmodel.py | 10 | ||||
-rw-r--r-- | rpython/rlib/test/test_objectmodel.py | 37 |
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 |