[pypy-svn] pypy out-of-line-guards-2: Implement quasi-immutable fields which contain immutable lists,
arigo
commits-noreply at bitbucket.org
Tue May 3 20:43:47 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: out-of-line-guards-2
Changeset: r43865:c965adb0f4da
Date: 2011-05-03 20:21 +0200
http://bitbucket.org/pypy/pypy/changeset/c965adb0f4da/
Log: Implement quasi-immutable fields which contain immutable lists,
defined with _immutable_fields_ = ['foo?[*]'].
It actually means that 'foo' is a regular quasi-immutable field, and
that all list accesses we do directly by 'obj.foo[index]' are
supposed to read the **immutable** content of the list. The content
of the list is not itself quasi-immutable. Hence the precise
notation: 'lst?[*]', and not 'lst[*]?'.
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -638,16 +638,19 @@
return None
def maybe_return_immutable_list(self, attr, s_result):
- # hack: 'x.lst' where lst is listed in _immutable_fields_ as 'lst[*]'
+ # hack: 'x.lst' where lst is listed in _immutable_fields_ as
+ # either 'lst[*]' or 'lst?[*]'
# should really return an immutable list as a result. Implemented
# by changing the result's annotation (but not, of course, doing an
# actual copy in the rtyper). Tested in pypy.rpython.test.test_rlist,
# test_immutable_list_out_of_instance.
- search = '%s[*]' % (attr,)
+ search1 = '%s[*]' % (attr,)
+ search2 = '%s?[*]' % (attr,)
cdesc = self
while cdesc is not None:
if '_immutable_fields_' in cdesc.classdict:
- if search in cdesc.classdict['_immutable_fields_'].value:
+ if (search1 in cdesc.classdict['_immutable_fields_'].value or
+ search2 in cdesc.classdict['_immutable_fields_'].value):
s_result.listdef.never_resize()
s_copy = s_result.listdef.offspring()
s_copy.listdef.mark_as_immutable()
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -3391,6 +3391,20 @@
s = a.build_types(f, [int])
assert s.listdef.listitem.immutable
+ def test_return_immutable_list_quasiimmut_field(self):
+ class A:
+ _immutable_fields_ = 'lst?[*]'
+ def f(n):
+ a = A()
+ l1 = [n, 0]
+ l1[1] = n+1
+ a.lst = l1
+ return a.lst
+
+ a = self.RPythonAnnotator()
+ s = a.build_types(f, [int])
+ assert s.listdef.listitem.immutable
+
def test_immutable_list_is_actually_resized(self):
class A:
_immutable_fields_ = 'lst[*]'
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -10,6 +10,7 @@
from pypy.jit.codewriter.policy import log
from pypy.jit.metainterp.typesystem import deref, arrayItem
from pypy.jit.metainterp import quasiimmut
+from pypy.rpython.rclass import IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY
from pypy.rlib import objectmodel
from pypy.rlib.jit import _we_are_jitted
from pypy.translator.simplify import get_funcobj
@@ -114,7 +115,7 @@
"known non-negative, or catching IndexError, or\n"
"not inlining at all (for tests: use listops=True).\n"
"Occurred in: %r" % self.graph)
- # extra expanation: with the way things are organized in
+ # extra explanation: with the way things are organized in
# rpython/rlist.py, the ll_getitem becomes a function call
# that is typically meant to be inlined by the JIT, but
# this does not work with vable arrays because
@@ -579,7 +580,7 @@
op1 = SpaceOperation('getfield_%s_%s%s' % (argname, kind, pure),
[v_inst, descr], op.result)
#
- if immut is quasiimmut.IR_QUASI_IMMUTABLE:
+ if immut in (IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY):
descr1 = self.cpu.fielddescrof(
v_inst.concretetype.TO,
quasiimmut.get_mutate_field_name(c_fieldname.value))
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -949,9 +949,9 @@
assert op1.args[3] == ListOfKind('ref', [v1, v2])
def test_quasi_immutable():
- from pypy.rpython.rclass import FieldListAccessor, IR_QUASI_IMMUTABLE
+ from pypy.rpython.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
accessor = FieldListAccessor()
- accessor.initialize(None, {'inst_x': IR_QUASI_IMMUTABLE})
+ accessor.initialize(None, {'inst_x': IR_QUASIIMMUTABLE})
v2 = varoftype(lltype.Signed)
STRUCT = lltype.GcStruct('struct', ('inst_x', lltype.Signed),
('mutate_x', rclass.OBJECTPTR),
@@ -974,9 +974,9 @@
assert op2.result is op.result
def test_quasi_immutable_setfield():
- from pypy.rpython.rclass import FieldListAccessor, IR_QUASI_IMMUTABLE
+ from pypy.rpython.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
accessor = FieldListAccessor()
- accessor.initialize(None, {'inst_x': IR_QUASI_IMMUTABLE})
+ accessor.initialize(None, {'inst_x': IR_QUASIIMMUTABLE})
v1 = varoftype(lltype.Signed)
STRUCT = lltype.GcStruct('struct', ('inst_x', lltype.Signed),
('mutate_x', rclass.OBJECTPTR),
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -570,6 +570,11 @@
# During tracing, a 'jit_force_quasi_immutable' usually turns into
# the operations that check that the content of 'mutate_xxx' is null.
# If it is actually not null already now, then we abort tracing.
+ # The idea is that if we use 'jit_force_quasi_immutable' on a freshly
+ # allocated object, then the GETFIELD_GC will know that the answer is
+ # null, and the guard will be removed. So the fact that the field is
+ # quasi-immutable will have no effect, and instead it will work as a
+ # regular, probably virtual, structure.
mutatebox = self.execute_with_descr(rop.GETFIELD_GC,
mutatefielddescr, box)
if mutatebox.nonnull():
diff --git a/pypy/jit/metainterp/quasiimmut.py b/pypy/jit/metainterp/quasiimmut.py
--- a/pypy/jit/metainterp/quasiimmut.py
+++ b/pypy/jit/metainterp/quasiimmut.py
@@ -1,15 +1,9 @@
import weakref
-from pypy.rpython.rclass import IR_QUASI_IMMUTABLE
from pypy.rpython.lltypesystem import lltype, rclass
from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
from pypy.jit.metainterp.history import AbstractDescr
-def is_quasi_immutable(STRUCT, fieldname):
- imm_fields = STRUCT._hints.get('immutable_fields')
- return (imm_fields is not None and
- imm_fields.fields.get(fieldname) is IR_QUASI_IMMUTABLE)
-
def get_mutate_field_name(fieldname):
if fieldname.startswith('inst_'): # lltype
return 'mutate_' + fieldname[5:]
diff --git a/pypy/jit/metainterp/test/test_optimizeutil.py b/pypy/jit/metainterp/test/test_optimizeutil.py
--- a/pypy/jit/metainterp/test/test_optimizeutil.py
+++ b/pypy/jit/metainterp/test/test_optimizeutil.py
@@ -3,7 +3,7 @@
from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
-from pypy.rpython.rclass import FieldListAccessor, IR_QUASI_IMMUTABLE
+from pypy.rpython.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
from pypy.jit.backend.llgraph import runner
from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr,
@@ -65,7 +65,7 @@
otherdescr = cpu.fielddescrof(NODE2, 'other')
accessor = FieldListAccessor()
- accessor.initialize(None, {'inst_field': IR_QUASI_IMMUTABLE})
+ accessor.initialize(None, {'inst_field': IR_QUASIIMMUTABLE})
QUASI = lltype.GcStruct('QUASIIMMUT', ('inst_field', lltype.Signed),
('mutate_field', rclass.OBJECTPTR),
hints={'immutable_fields': accessor})
diff --git a/pypy/jit/metainterp/test/test_quasiimmut.py b/pypy/jit/metainterp/test/test_quasiimmut.py
--- a/pypy/jit/metainterp/test/test_quasiimmut.py
+++ b/pypy/jit/metainterp/test/test_quasiimmut.py
@@ -2,7 +2,7 @@
import py
from pypy.rpython.lltypesystem import lltype, llmemory, rclass
-from pypy.rpython.rclass import FieldListAccessor, IR_QUASI_IMMUTABLE
+from pypy.rpython.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
from pypy.jit.metainterp import typesystem
from pypy.jit.metainterp.quasiimmut import QuasiImmut
from pypy.jit.metainterp.quasiimmut import get_current_qmut_instance
@@ -13,7 +13,7 @@
def test_get_current_qmut_instance():
accessor = FieldListAccessor()
- accessor.initialize(None, {'inst_x': IR_QUASI_IMMUTABLE})
+ accessor.initialize(None, {'inst_x': IR_QUASIIMMUTABLE})
STRUCT = lltype.GcStruct('Foo', ('inst_x', lltype.Signed),
('mutate_x', rclass.OBJECTPTR),
hints={'immutable_fields': accessor})
@@ -289,8 +289,71 @@
assert f(100, 15) == 3009
res = self.meta_interp(f, [100, 15])
assert res == 3009
- self.check_loops(guard_not_invalidated=2,
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0,
call_may_force=0, guard_not_forced=0)
+ def test_list_simple_1(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['lst?[*]']
+ def __init__(self, lst):
+ self.lst = lst
+ def f(a, x):
+ lst1 = [0, 0]
+ lst1[1] = a
+ foo = Foo(lst1)
+ total = 0
+ while x > 0:
+ myjitdriver.jit_merge_point(foo=foo, x=x, total=total)
+ # read a quasi-immutable field out of a Constant
+ total += foo.lst[1]
+ x -= 1
+ return total
+ #
+ res = self.meta_interp(f, [100, 7])
+ assert res == 700
+ self.check_loops(getfield_gc=0, getarrayitem_gc=0,
+ getarrayitem_gc_pure=0, everywhere=True)
+ #
+ from pypy.jit.metainterp.warmspot import get_stats
+ loops = get_stats().loops
+ for loop in loops:
+ assert len(loop.quasi_immutable_deps) == 1
+ assert isinstance(loop.quasi_immutable_deps.keys()[0], QuasiImmut)
+
+ def test_list_change_during_running(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['lst?[*]']
+ def __init__(self, lst):
+ self.lst = lst
+ @dont_look_inside
+ def residual_call(foo, x):
+ if x == 5:
+ lst2 = [0, 0]
+ lst2[1] = foo.lst[1] + 1
+ foo.lst = lst2
+ def f(a, x):
+ lst1 = [0, 0]
+ lst1[1] = a
+ foo = Foo(lst1)
+ total = 0
+ while x > 0:
+ myjitdriver.jit_merge_point(foo=foo, x=x, total=total)
+ # read a quasi-immutable field out of a Constant
+ total += foo.lst[1]
+ residual_call(foo, x)
+ total += foo.lst[1]
+ x -= 1
+ return total
+ #
+ assert f(100, 15) == 3009
+ res = self.meta_interp(f, [100, 15])
+ assert res == 3009
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0,
+ getarrayitem_gc=0, getarrayitem_gc_pure=0,
+ call_may_force=0, guard_not_forced=0)
+
+
class TestLLtypeGreenFieldsTests(QuasiImmutTests, LLJitMixin):
pass
diff --git a/pypy/jit/metainterp/test/test_virtualizable.py b/pypy/jit/metainterp/test/test_virtualizable.py
--- a/pypy/jit/metainterp/test/test_virtualizable.py
+++ b/pypy/jit/metainterp/test/test_virtualizable.py
@@ -2,7 +2,7 @@
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory
from pypy.rpython.annlowlevel import llhelper
-from pypy.rpython.rclass import IR_IMMUTABLE, IR_ARRAY_IMMUTABLE
+from pypy.rpython.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY
from pypy.jit.codewriter.policy import StopAtXPolicy
from pypy.jit.codewriter import heaptracker
from pypy.rlib.jit import JitDriver, hint, dont_look_inside
@@ -212,7 +212,7 @@
hints = {'virtualizable2_accessor': FieldListAccessor()})
XY2._hints['virtualizable2_accessor'].initialize(
XY2, {'inst_x' : IR_IMMUTABLE,
- 'inst_l1' : IR_ARRAY_IMMUTABLE, 'inst_l2' : IR_ARRAY_IMMUTABLE})
+ 'inst_l1' : IR_IMMUTABLE_ARRAY, 'inst_l2' : IR_IMMUTABLE_ARRAY})
xy2_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
heaptracker.set_testing_vtable_for_gcstruct(XY2, xy2_vtable, 'XY2')
diff --git a/pypy/jit/metainterp/virtualizable.py b/pypy/jit/metainterp/virtualizable.py
--- a/pypy/jit/metainterp/virtualizable.py
+++ b/pypy/jit/metainterp/virtualizable.py
@@ -1,7 +1,7 @@
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.rpython.rclass import IR_ARRAY_IMMUTABLE, IR_IMMUTABLE
+from pypy.rpython.rclass import IR_IMMUTABLE_ARRAY, IR_IMMUTABLE
from pypy.rpython import rvirtualizable2
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.unroll import unrolling_iterable
@@ -35,7 +35,7 @@
static_fields = []
array_fields = []
for name, tp in all_fields.iteritems():
- if tp == IR_ARRAY_IMMUTABLE:
+ if tp == IR_IMMUTABLE_ARRAY:
array_fields.append(name)
elif tp == IR_IMMUTABLE:
static_fields.append(name)
diff --git a/pypy/rpython/lltypesystem/test/test_lloperation.py b/pypy/rpython/lltypesystem/test/test_lloperation.py
--- a/pypy/rpython/lltypesystem/test/test_lloperation.py
+++ b/pypy/rpython/lltypesystem/test/test_lloperation.py
@@ -87,7 +87,8 @@
assert llop.getarraysize.is_pure([v_a2])
#
for kind in [rclass.IR_MUTABLE, rclass.IR_IMMUTABLE,
- rclass.IR_ARRAY_IMMUTABLE, rclass.IR_QUASI_IMMUTABLE]:
+ rclass.IR_IMMUTABLE_ARRAY, rclass.IR_QUASIIMMUTABLE,
+ rclass.IR_QUASIIMMUTABLE_ARRAY]:
accessor = rclass.FieldListAccessor()
S3 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
hints={'immutable_fields': accessor})
@@ -114,13 +115,14 @@
assert llop.getinteriorfield(lltype.Signed, s2, 'x') == 45
#
for kind in [rclass.IR_MUTABLE, rclass.IR_IMMUTABLE,
- rclass.IR_ARRAY_IMMUTABLE, rclass.IR_QUASI_IMMUTABLE]:
+ rclass.IR_IMMUTABLE_ARRAY, rclass.IR_QUASIIMMUTABLE,
+ rclass.IR_QUASIIMMUTABLE_ARRAY]:
#
S3 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
hints={'immutable_fields': accessor})
accessor.initialize(S3, {'x': kind})
s3 = lltype.malloc(S3); s3.x = 46; s3.y = 47
- if kind in [rclass.IR_IMMUTABLE, rclass.IR_ARRAY_IMMUTABLE]:
+ if kind in [rclass.IR_IMMUTABLE, rclass.IR_IMMUTABLE_ARRAY]:
assert llop.getfield(lltype.Signed, s3, 'x') == 46
assert llop.getinteriorfield(lltype.Signed, s3, 'x') == 46
else:
diff --git a/pypy/rpython/rclass.py b/pypy/rpython/rclass.py
--- a/pypy/rpython/rclass.py
+++ b/pypy/rpython/rclass.py
@@ -31,10 +31,11 @@
def __repr__(self):
return '<%s>' % self.name
-IR_MUTABLE = ImmutableRanking('mutable', False)
-IR_IMMUTABLE = ImmutableRanking('immutable', True)
-IR_ARRAY_IMMUTABLE = ImmutableRanking('array_immutable', True)
-IR_QUASI_IMMUTABLE = ImmutableRanking('quasi_immutable', False)
+IR_MUTABLE = ImmutableRanking('mutable', False)
+IR_IMMUTABLE = ImmutableRanking('immutable', True)
+IR_IMMUTABLE_ARRAY = ImmutableRanking('immutable_array', True)
+IR_QUASIIMMUTABLE = ImmutableRanking('quasiimmutable', False)
+IR_QUASIIMMUTABLE_ARRAY = ImmutableRanking('quasiimmutable_array', False)
class ImmutableConflictError(Exception):
"""Raised when the _immutable_ or _immutable_fields_ hints are
@@ -229,12 +230,15 @@
def _parse_field_list(self, fields, accessor):
ranking = {}
for name in fields:
- if name.endswith('[*]'): # for virtualizables' lists
+ if name.endswith('?[*]'): # a quasi-immutable field pointing to
+ name = name[:-4] # an immutable array
+ rank = IR_QUASIIMMUTABLE_ARRAY
+ elif name.endswith('[*]'): # for virtualizables' lists
name = name[:-3]
- rank = IR_ARRAY_IMMUTABLE
+ rank = IR_IMMUTABLE_ARRAY
elif name.endswith('?'): # a quasi-immutable field
name = name[:-1]
- rank = IR_QUASI_IMMUTABLE
+ rank = IR_QUASIIMMUTABLE
else: # a regular immutable/green field
rank = IR_IMMUTABLE
try:
@@ -284,10 +288,12 @@
llops.genop('jit_force_quasi_immutable', [vinst, c_fieldname])
def is_quasi_immutable(self, fieldname):
- search = fieldname + '?'
+ search1 = fieldname + '?'
+ search2 = fieldname + '?[*]'
rbase = self
while rbase.classdef is not None:
- if search in rbase.immutable_field_set:
+ if (search1 in rbase.immutable_field_set or
+ search2 in rbase.immutable_field_set):
return True
rbase = rbase.rbase
return False
diff --git a/pypy/rpython/test/test_rclass.py b/pypy/rpython/test/test_rclass.py
--- a/pypy/rpython/test/test_rclass.py
+++ b/pypy/rpython/test/test_rclass.py
@@ -5,8 +5,8 @@
from pypy.rpython.ootypesystem import ootype
from pypy.rlib.rarithmetic import intmask, r_longlong
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
-from pypy.rpython.rclass import IR_IMMUTABLE, IR_ARRAY_IMMUTABLE
-from pypy.rpython.rclass import IR_QUASI_IMMUTABLE
+from pypy.rpython.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY
+from pypy.rpython.rclass import IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY
from pypy.objspace.flow.model import summary
class EmptyBase(object):
@@ -749,9 +749,9 @@
A_TYPE = deref(graph.getreturnvar().concretetype)
accessor = A_TYPE._hints["immutable_fields"]
assert accessor.fields == {"inst_x": IR_IMMUTABLE,
- "inst_y": IR_ARRAY_IMMUTABLE} or \
+ "inst_y": IR_IMMUTABLE_ARRAY} or \
accessor.fields == {"ox": IR_IMMUTABLE,
- "oy": IR_ARRAY_IMMUTABLE} # for ootype
+ "oy": IR_IMMUTABLE_ARRAY} # for ootype
def test_immutable_fields_subclass_1(self):
from pypy.jit.metainterp.typesystem import deref
@@ -921,17 +921,38 @@
B_TYPE = deref(graph.getreturnvar().concretetype)
accessor = B_TYPE._hints["immutable_fields"]
assert accessor.fields == {"inst_y": IR_IMMUTABLE,
- "inst_b": IR_QUASI_IMMUTABLE} or \
+ "inst_b": IR_QUASIIMMUTABLE} or \
accessor.fields == {"ox": IR_IMMUTABLE,
"oy": IR_IMMUTABLE,
- "oa": IR_QUASI_IMMUTABLE,
- "ob": IR_QUASI_IMMUTABLE} # for ootype
+ "oa": IR_QUASIIMMUTABLE,
+ "ob": IR_QUASIIMMUTABLE} # for ootype
found = []
for op in graph.startblock.operations:
if op.opname == 'jit_force_quasi_immutable':
found.append(op.args[1].value)
assert found == ['mutate_a', 'mutate_a', 'mutate_b']
+ def test_quasi_immutable_array(self):
+ from pypy.jit.metainterp.typesystem import deref
+ class A(object):
+ _immutable_fields_ = ['c?[*]']
+ class B(A):
+ pass
+ def f():
+ a = A()
+ a.c = [3, 4, 5]
+ return A()
+ t, typer, graph = self.gengraph(f, [])
+ A_TYPE = deref(graph.getreturnvar().concretetype)
+ accessor = A_TYPE._hints["immutable_fields"]
+ assert accessor.fields == {"inst_c": IR_QUASIIMMUTABLE_ARRAY} or \
+ accessor.fields == {"oc": IR_QUASIIMMUTABLE_ARRAY} # for ootype
+ found = []
+ for op in graph.startblock.operations:
+ if op.opname == 'jit_force_quasi_immutable':
+ found.append(op.args[1].value)
+ assert found == ['mutate_c']
+
class TestLLtype(BaseTestRclass, LLRtypeMixin):
diff --git a/pypy/rpython/test/test_rvirtualizable2.py b/pypy/rpython/test/test_rvirtualizable2.py
--- a/pypy/rpython/test/test_rvirtualizable2.py
+++ b/pypy/rpython/test/test_rvirtualizable2.py
@@ -5,7 +5,7 @@
from pypy.rlib.jit import hint
from pypy.objspace.flow.model import summary
from pypy.rpython.llinterp import LLInterpreter
-from pypy.rpython.rclass import IR_IMMUTABLE, IR_ARRAY_IMMUTABLE
+from pypy.rpython.rclass import IR_IMMUTABLE, IR_IMMUTABLE_ARRAY
from pypy import conftest
@@ -118,7 +118,7 @@
accessor = TYPE._hints['virtualizable2_accessor']
assert accessor.TYPE == TYPE
assert accessor.fields == {self.prefix + 'v1': IR_IMMUTABLE,
- self.prefix + 'v2': IR_ARRAY_IMMUTABLE}
+ self.prefix + 'v2': IR_IMMUTABLE_ARRAY}
#
def fn2(n):
Base().base1 = 42
More information about the Pypy-commit
mailing list