[pypy-svn] r68929 - in pypy/branch/jit-removetypeptr/pypy: config jit/backend/llsupport jit/backend/llsupport/test jit/backend/x86 jit/backend/x86/test rpython rpython/lltypesystem rpython/memory rpython/memory/gc/test rpython/memory/gctransform rpython/memory/test translator/c translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Tue Nov 3 11:42:37 CET 2009
Author: arigo
Date: Tue Nov 3 11:42:36 2009
New Revision: 68929
Modified:
pypy/branch/jit-removetypeptr/pypy/config/translationoption.py
pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/gc.py
pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/llmodel.py
pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/test/test_gc.py
pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/assembler.py
pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/ri386setup.py
pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/test/test_ri386_auto_encoding.py
pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/test/test_zrpy_gc.py
pypy/branch/jit-removetypeptr/pypy/rpython/llinterp.py
pypy/branch/jit-removetypeptr/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/jit-removetypeptr/pypy/rpython/memory/gc/test/test_direct.py
pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctransform/framework.py
pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctransform/transform.py
pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctypelayout.py
pypy/branch/jit-removetypeptr/pypy/rpython/memory/test/test_gctypelayout.py
pypy/branch/jit-removetypeptr/pypy/rpython/memory/test/test_transformed_gc.py
pypy/branch/jit-removetypeptr/pypy/translator/c/database.py
pypy/branch/jit-removetypeptr/pypy/translator/c/node.py
pypy/branch/jit-removetypeptr/pypy/translator/c/test/test_newgc.py
Log:
Implement jit support for gcremovetypeptr.
Modified: pypy/branch/jit-removetypeptr/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/config/translationoption.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/config/translationoption.py Tue Nov 3 11:42:36 2009
@@ -95,8 +95,7 @@
# JIT generation: use -Ojit to enable it
BoolOption("jit", "generate a JIT",
default=False,
- requires=[("translation.thread", False),
- ("translation.gcremovetypeptr", False)],
+ requires=[("translation.thread", False)],
suggests=[("translation.gc", "hybrid"), # or "boehm"
("translation.gcrootfinder", "asmgcc"),
("translation.list_comprehension_operations", True)]),
Modified: pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/gc.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/gc.py Tue Nov 3 11:42:36 2009
@@ -325,8 +325,7 @@
# make a TransformerLayoutBuilder and save it on the translator
# where it can be fished and reused by the FrameworkGCTransformer
- self.layoutbuilder = framework.JITTransformerLayoutBuilder(
- gcdescr.config)
+ self.layoutbuilder = framework.TransformerLayoutBuilder(translator)
self.layoutbuilder.delay_encoding()
self.translator._jit2gc = {
'layoutbuilder': self.layoutbuilder,
Modified: pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/llmodel.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/llmodel.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/llmodel.py Tue Nov 3 11:42:36 2009
@@ -28,8 +28,11 @@
else:
translator = None
self.gc_ll_descr = get_ll_description(gcdescr, translator)
- self.vtable_offset, _ = symbolic.get_field_token(rclass.OBJECT,
- 'typeptr',
+ if translator and translator.config.translation.gcremovetypeptr:
+ self.vtable_offset = None
+ else:
+ self.vtable_offset, _ = symbolic.get_field_token(rclass.OBJECT,
+ 'typeptr',
translate_support_code)
self._setup_prebuilt_error('ovf', OverflowError)
self._setup_prebuilt_error('zer', ZeroDivisionError)
@@ -424,8 +427,9 @@
classint = classbox.getint()
descrsize = self.class_sizes[classint]
res = self.gc_ll_descr.gc_malloc(descrsize)
- as_array = rffi.cast(rffi.CArrayPtr(lltype.Signed), res)
- as_array[self.vtable_offset/WORD] = classint
+ if self.vtable_offset is not None:
+ as_array = rffi.cast(rffi.CArrayPtr(lltype.Signed), res)
+ as_array[self.vtable_offset/WORD] = classint
return BoxPtr(res)
def do_new_array(self, countbox, arraydescr):
Modified: pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/test/test_gc.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/test/test_gc.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/jit/backend/llsupport/test/test_gc.py Tue Nov 3 11:42:36 2009
@@ -147,19 +147,20 @@
class TestFramework:
def setup_method(self, meth):
- class FakeTranslator:
- pass
- class config:
+ class config_:
class translation:
gc = 'hybrid'
gcrootfinder = 'asmgcc'
gctransformer = 'framework'
+ gcremovetypeptr = False
+ class FakeTranslator:
+ config = config_
class FakeCPU:
def cast_adr_to_int(self, adr):
ptr = llmemory.cast_adr_to_ptr(adr, gc_ll_descr.WB_FUNCPTR)
assert ptr._obj._callable == llop1._write_barrier_failing_case
return 42
- gcdescr = get_description(config)
+ gcdescr = get_description(config_)
translator = FakeTranslator()
llop1 = FakeLLOp()
gc_ll_descr = GcLLDescr_framework(gcdescr, FakeTranslator(), llop1)
Modified: pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/assembler.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/assembler.py Tue Nov 3 11:42:36 2009
@@ -518,7 +518,8 @@
self.set_vtable(eax, loc_vtable)
def set_vtable(self, loc, loc_vtable):
- self.mc.MOV(mem(loc, self.cpu.vtable_offset), loc_vtable)
+ if self.cpu.vtable_offset is not None:
+ self.mc.MOV(mem(loc, self.cpu.vtable_offset), loc_vtable)
# XXX genop_new is abused for all varsized mallocs with Boehm, for now
# (instead of genop_new_array, genop_newstr, genop_newunicode)
@@ -713,7 +714,24 @@
def genop_guard_guard_class(self, ign_1, guard_op, addr, locs, ign_2):
offset = self.cpu.vtable_offset
- self.mc.CMP(mem(locs[0], offset), locs[1])
+ if offset is not None:
+ self.mc.CMP(mem(locs[0], offset), locs[1])
+ else:
+ # XXX hard-coded assumption: to go from an object to its class
+ # we use the following algorithm:
+ # - read the typeid from mem(locs[0]), i.e. at offset 0
+ # - keep the lower 16 bits read there
+ # - multiply by 4 and use it as an offset in type_info_group.
+ loc = locs[1]
+ assert isinstance(loc, IMM32)
+ classptr = loc.value
+ # here, we have to go back from 'classptr' to the value expected
+ # from reading the 16 bits in the object header
+ type_info_group = llop.gc_get_type_info_group(llmemory.Address)
+ type_info_group = rffi.cast(lltype.Signed, type_info_group)
+ expected_typeid = (classptr - type_info_group) >> 2
+ self.mc.CMP16(mem(locs[0], 0), imm32(expected_typeid))
+ #
return self.implement_guard(addr, self.mc.JNE)
def _no_const_locs(self, args):
Modified: pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/ri386setup.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/ri386setup.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/ri386setup.py Tue Nov 3 11:42:36 2009
@@ -310,6 +310,11 @@
CMP = Instruction()
CMP.common_modes(7)
+# special mode for comparing a 16-bit operand with an immediate
+CMP16 = Instruction()
+CMP16.mode2(MODRM, IMM32, ['\x66', '\x81', orbyte(7<<3), modrm(1),
+ immediate(2,'h')])
+
NOP = Instruction()
NOP.mode0(['\x90'])
Modified: pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/test/test_ri386_auto_encoding.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/test/test_ri386_auto_encoding.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/test/test_ri386_auto_encoding.py Tue Nov 3 11:42:36 2009
@@ -218,6 +218,8 @@
return [] # MOV [constant-address], accum
if instrname == "MOV16":
return [] # skipped
+ if instrname == "CMP16":
+ return [] # skipped
if instrname == "LEA":
if (args[1][1].__class__ != i386.MODRM or
args[1][1].is_register()):
Modified: pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/test/test_zrpy_gc.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/test/test_zrpy_gc.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/jit/backend/x86/test/test_zrpy_gc.py Tue Nov 3 11:42:36 2009
@@ -78,6 +78,7 @@
#
t = TranslationContext()
t.config.translation.gc = gc
+ t.config.translation.gcremovetypeptr = True
for name, value in kwds.items():
setattr(t.config.translation, name, value)
ann = t.buildannotator(policy=annpolicy.StrictAnnotatorPolicy())
Modified: pypy/branch/jit-removetypeptr/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/rpython/llinterp.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/rpython/llinterp.py Tue Nov 3 11:42:36 2009
@@ -890,6 +890,9 @@
def op_gc_stack_bottom(self):
pass # marker for trackgcroot.py
+ def op_gc_get_type_info_group(self):
+ raise NotImplementedError("gc_get_type_info_group")
+
def op_do_malloc_fixedsize_clear(self):
raise NotImplementedError("do_malloc_fixedsize_clear")
Modified: pypy/branch/jit-removetypeptr/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/rpython/lltypesystem/lloperation.py Tue Nov 3 11:42:36 2009
@@ -432,6 +432,7 @@
'do_malloc_fixedsize_clear': LLOp(canunwindgc=True),
'do_malloc_varsize_clear': LLOp(canunwindgc=True),
'get_write_barrier_failing_case': LLOp(sideeffects=False),
+ 'gc_get_type_info_group': LLOp(sideeffects=False),
# __________ GC operations __________
Modified: pypy/branch/jit-removetypeptr/pypy/rpython/memory/gc/test/test_direct.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/rpython/memory/gc/test/test_direct.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/rpython/memory/gc/test/test_direct.py Tue Nov 3 11:42:36 2009
@@ -68,7 +68,7 @@
self.gc.DEBUG = True
self.rootwalker = DirectRootWalker(self)
self.gc.set_root_walker(self.rootwalker)
- self.layoutbuilder = TypeLayoutBuilder(self.GCClass, {})
+ self.layoutbuilder = TypeLayoutBuilder(self.GCClass)
self.get_type_id = self.layoutbuilder.get_type_id
self.layoutbuilder.initialize_gc_query_function(self.gc)
self.gc.setup()
Modified: pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctransform/framework.py Tue Nov 3 11:42:36 2009
@@ -130,12 +130,7 @@
if hasattr(translator, '_jit2gc'):
self.layoutbuilder = translator._jit2gc['layoutbuilder']
else:
- if translator.config.translation.gcremovetypeptr:
- lltype2vtable = translator.rtyper.lltype2vtable
- else:
- lltype2vtable = {}
- self.layoutbuilder = TransformerLayoutBuilder(GCClass,
- lltype2vtable)
+ self.layoutbuilder = TransformerLayoutBuilder(translator, GCClass)
self.layoutbuilder.transformer = self
self.get_type_id = self.layoutbuilder.get_type_id
@@ -508,11 +503,16 @@
self.write_typeid_list()
return newgcdependencies
- def get_final_dependencies(self):
- # returns an iterator enumerating the type_info_group's members,
- # to make sure that they are all followed (only a part of them
- # might have been followed by a previous enum_dependencies()).
- return iter(self.layoutbuilder.type_info_group.members)
+ def get_finish_tables(self):
+ # We must first make sure that the type_info_group's members
+ # are all followed. Do it repeatedly while new members show up.
+ # Once it is really done, do finish_tables().
+ seen = 0
+ while seen < len(self.layoutbuilder.type_info_group.members):
+ curtotal = len(self.layoutbuilder.type_info_group.members)
+ yield self.layoutbuilder.type_info_group.members[seen:curtotal]
+ seen = curtotal
+ yield self.finish_tables()
def write_typeid_list(self):
"""write out the list of type ids together with some info"""
@@ -821,6 +821,9 @@
if hasattr(self.root_walker, 'thread_die_ptr'):
hop.genop("direct_call", [self.root_walker.thread_die_ptr])
+ def gct_gc_get_type_info_group(self, hop):
+ return hop.cast_result(self.c_type_info_group)
+
def gct_malloc_nonmovable_varsize(self, hop):
TYPE = hop.spaceop.result.concretetype
if self.gcdata.gc.can_malloc_nonmovable():
@@ -964,6 +967,16 @@
class TransformerLayoutBuilder(gctypelayout.TypeLayoutBuilder):
+ def __init__(self, translator, GCClass=None):
+ if GCClass is None:
+ from pypy.rpython.memory.gc.base import choose_gc_from_config
+ GCClass, _ = choose_gc_from_config(translator.config)
+ if translator.config.translation.gcremovetypeptr:
+ lltype2vtable = translator.rtyper.lltype2vtable
+ else:
+ lltype2vtable = None
+ super(TransformerLayoutBuilder, self).__init__(GCClass, lltype2vtable)
+
def has_finalizer(self, TYPE):
rtti = get_rtti(TYPE)
return rtti is not None and hasattr(rtti._obj, 'destructor_funcptr')
@@ -990,18 +1003,6 @@
return fptr
-class JITTransformerLayoutBuilder(TransformerLayoutBuilder):
- # for the JIT: currently does not support removetypeptr
- def __init__(self, config):
- from pypy.rpython.memory.gc.base import choose_gc_from_config
- try:
- assert not config.translation.gcremovetypeptr
- except AttributeError: # for some tests
- pass
- GCClass, _ = choose_gc_from_config(config)
- TransformerLayoutBuilder.__init__(self, GCClass, {})
-
-
def gen_zero_gc_pointers(TYPE, v, llops, previous_steps=None):
if previous_steps is None:
previous_steps = []
Modified: pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctransform/transform.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctransform/transform.py Tue Nov 3 11:42:36 2009
@@ -312,12 +312,12 @@
newgcdependencies = self.ll_finalizers_ptrs
return newgcdependencies
- def get_final_dependencies(self):
- pass
-
def finish_tables(self):
pass
+ def get_finish_tables(self):
+ return self.finish_tables
+
def finish(self, backendopt=True):
self.finish_helpers(backendopt=backendopt)
self.finish_tables()
Modified: pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/rpython/memory/gctypelayout.py Tue Nov 3 11:42:36 2009
@@ -1,4 +1,5 @@
from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup
+from pypy.rpython.lltypesystem import rclass
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.debug import ll_assert
@@ -169,7 +170,7 @@
size_of_fixed_type_info = llmemory.sizeof(GCData.TYPE_INFO)
- def __init__(self, GCClass, lltype2vtable):
+ def __init__(self, GCClass, lltype2vtable=None):
self.GCClass = GCClass
self.lltype2vtable = lltype2vtable
self.make_type_info_group()
@@ -218,16 +219,28 @@
# store it
type_id = self.type_info_group.add_member(fullinfo)
self.id_of_type[TYPE] = type_id
- # store the vtable of the type (if any) immediately thereafter
- # (note that if gcremovetypeptr is False, lltype2vtable is empty)
- vtable = self.lltype2vtable.get(TYPE, None)
- if vtable is not None:
- # check that if we have a vtable, we are not varsize
- assert lltype.typeOf(fullinfo) == GCData.TYPE_INFO_PTR
- vtable = lltype.normalizeptr(vtable)
- self.type_info_group.add_member(vtable)
+ self.add_vtable_after_typeinfo(TYPE)
return type_id
+ def add_vtable_after_typeinfo(self, TYPE):
+ # if gcremovetypeptr is False, then lltype2vtable is None and it
+ # means that we don't have to store the vtables in type_info_group.
+ if self.lltype2vtable is None:
+ return
+ # does the type have a vtable?
+ vtable = self.lltype2vtable.get(TYPE, None)
+ if vtable is not None:
+ # yes. check that in this case, we are not varsize
+ assert not TYPE._is_varsize()
+ vtable = lltype.normalizeptr(vtable)
+ self.type_info_group.add_member(vtable)
+ else:
+ # no vtable from lltype2vtable -- double-check to be sure
+ # that it's not a subclass of OBJECT.
+ while isinstance(TYPE, lltype.GcStruct):
+ assert TYPE is not rclass.OBJECT
+ _, TYPE = TYPE._first_struct()
+
def get_info(self, type_id):
return llop.get_group_member(GCData.TYPE_INFO_PTR,
self.type_info_group._as_ptr(),
Modified: pypy/branch/jit-removetypeptr/pypy/rpython/memory/test/test_gctypelayout.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/rpython/memory/test/test_gctypelayout.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/rpython/memory/test/test_gctypelayout.py Tue Nov 3 11:42:36 2009
@@ -37,7 +37,7 @@
for T, c in [(GC_S, 0), (GC_S2, 2), (GC_A, 0), (GC_A2, 0), (GC_S3, 2)]:
assert len(offsets_to_gc_pointers(T)) == c
-def test_layout_builder(lltype2vtable={}):
+def test_layout_builder(lltype2vtable=None):
# XXX a very minimal test
layoutbuilder = TypeLayoutBuilder(FakeGC, lltype2vtable)
for T1, T2 in [(GC_A, GC_S), (GC_A2, GC_S2), (GC_S3, GC_S2)]:
@@ -67,7 +67,7 @@
layoutbuilder.size_of_fixed_type_info)
def test_constfold():
- layoutbuilder = TypeLayoutBuilder(FakeGC, {})
+ layoutbuilder = TypeLayoutBuilder(FakeGC)
tid1 = layoutbuilder.get_type_id(GC_A)
tid2 = layoutbuilder.get_type_id(GC_S3)
class MockGC:
Modified: pypy/branch/jit-removetypeptr/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/rpython/memory/test/test_transformed_gc.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/rpython/memory/test/test_transformed_gc.py Tue Nov 3 11:42:36 2009
@@ -709,9 +709,7 @@
if jit2gc:
return jit2gc['layoutbuilder']
GCClass = cls.gcpolicy.transformerclass.GCClass
- lltype2vtable = translator.rtyper.lltype2vtable
- layoutbuilder = framework.TransformerLayoutBuilder(GCClass,
- lltype2vtable)
+ layoutbuilder = framework.TransformerLayoutBuilder(translator, GCClass)
layoutbuilder.delay_encoding()
translator._jit2gc = {
'layoutbuilder': layoutbuilder,
Modified: pypy/branch/jit-removetypeptr/pypy/translator/c/database.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/translator/c/database.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/translator/c/database.py Tue Nov 3 11:42:36 2009
@@ -288,10 +288,8 @@
finish_callbacks.append(('Stackless transformer: finished',
self.stacklesstransformer.finish))
if self.gctransformer:
- finish_callbacks.append(('GC transformer: tracking vtables',
- self.gctransformer.get_final_dependencies))
finish_callbacks.append(('GC transformer: finished tables',
- self.gctransformer.finish_tables))
+ self.gctransformer.get_finish_tables()))
def add_dependencies(newdependencies):
for value in newdependencies:
@@ -336,8 +334,18 @@
if finish_callbacks:
logmsg, finish = finish_callbacks.pop(0)
- newdependencies = finish()
- log.database(logmsg)
+ if not hasattr(finish, 'next'):
+ newdependencies = finish()
+ else:
+ # if 'finish' is a generator, consume the next element
+ # and put the generator again in the queue
+ try:
+ newdependencies = finish.next()
+ finish_callbacks.insert(0, (None, finish))
+ except StopIteration:
+ newdependencies = None
+ if logmsg:
+ log.database(logmsg)
if newdependencies:
add_dependencies(newdependencies)
continue # progress - follow all dependencies again
Modified: pypy/branch/jit-removetypeptr/pypy/translator/c/node.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/translator/c/node.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/translator/c/node.py Tue Nov 3 11:42:36 2009
@@ -960,8 +960,8 @@
def enum_dependencies(self):
# note: for the group used by the GC, it can grow during this phase,
- # which means that we might not return all members yet. This is
- # fixed by finish_tables() in rpython/memory/gctransform/framework.py
+ # which means that we might not return all members yet. This is fixed
+ # by get_final_dependencies() in rpython.memory.gctransform.framework
for member in self.obj.members:
yield member._as_ptr()
Modified: pypy/branch/jit-removetypeptr/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/jit-removetypeptr/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/branch/jit-removetypeptr/pypy/translator/c/test/test_newgc.py Tue Nov 3 11:42:36 2009
@@ -949,6 +949,19 @@
class TestHybridGCRemoveTypePtr(TestHybridGC):
removetypeptr = True
+ def definestr_str_instance(cls):
+ class AbcDef:
+ pass
+ def fn(_):
+ a = AbcDef()
+ return str(a)
+ return fn
+
+ def test_str_instance(self):
+ res = self.run('str_instance')
+ assert res.startswith('<') and res.endswith('>')
+ assert 'AbcDef' in res
+
class TestMarkCompactGC(TestSemiSpaceGC):
gcpolicy = "markcompact"
More information about the Pypy-commit
mailing list