Given that a virtual is forced only right before it escapes, and the external call would flush the heap cache, what's the value there?
Alex On Wed, Jun 22, 2011 at 2:34 AM, Carl Friedrich Bolz <[email protected]> wrote: > Hi Alex, > > This is part of a more general problem: If a virtual is forced the heap > cache is not informed of the values that are written into the newly > allocated object. This is useful also for fields that are not > immutable. Do you maybe feel like generalizing this? > > Cheers, > > Carl Friedrich > > > On 06/21/2011 08:33 PM, alex_gaynor wrote: > >> Author: Alex Gaynor<[email protected]> >> Branch: >> Changeset: r45043:456273d0b54f >> Date: 2011-06-21 11:37 -0700 >> http://bitbucket.org/pypy/**pypy/changeset/456273d0b54f/<http://bitbucket.org/pypy/pypy/changeset/456273d0b54f/> >> >> Log: When a virtual is forced, and then subsequenly an immutable field >> is >> read out of it, the value is known if it was seen in a setfield, >> because it can't be set again by anything, therefore remove the >> getfield_gc_pure for it. Thanks to fijal for the review. >> >> diff --git a/pypy/jit/metainterp/**optimizeopt/heap.py >> b/pypy/jit/metainterp/**optimizeopt/heap.py >> --- a/pypy/jit/metainterp/**optimizeopt/heap.py >> +++ b/pypy/jit/metainterp/**optimizeopt/heap.py >> @@ -112,7 +112,7 @@ >> >> class OptHeap(Optimization): >> """Cache repeated heap accesses""" >> - >> + >> def __init__(self): >> # cached fields: {descr: CachedField} >> self.cached_fields = {} >> @@ -129,7 +129,7 @@ >> self.force_all_lazy_setfields(**) >> else: >> assert 0 # was: new.lazy_setfields = self.lazy_setfields >> - >> + >> for descr, d in self.cached_fields.items(): >> new.cached_fields[descr] = d.get_reconstructed(optimizer, >> valuemap) >> >> diff --git a/pypy/jit/metainterp/**optimizeopt/optimizer.py >> b/pypy/jit/metainterp/**optimizeopt/optimizer.py >> --- a/pypy/jit/metainterp/**optimizeopt/optimizer.py >> +++ b/pypy/jit/metainterp/**optimizeopt/optimizer.py >> @@ -141,6 +141,9 @@ >> # meaning it has been forced. >> return self.box is None >> >> + def is_forced_virtual(self): >> + return False >> + >> def getfield(self, ofs, default): >> raise NotImplementedError >> >> diff --git a/pypy/jit/metainterp/**optimizeopt/rewrite.py >> b/pypy/jit/metainterp/**optimizeopt/rewrite.py >> --- a/pypy/jit/metainterp/**optimizeopt/rewrite.py >> +++ b/pypy/jit/metainterp/**optimizeopt/rewrite.py >> @@ -219,7 +219,7 @@ >> break >> arg_consts.append(const) >> else: >> - # all constant arguments: check if we already know the reslut >> + # all constant arguments: check if we already know the result >> try: >> result = self.optimizer.call_pure_**results[arg_consts] >> except KeyError: >> diff --git a/pypy/jit/metainterp/**optimizeopt/test/test_**optimizeopt.py >> b/pypy/jit/metainterp/**optimizeopt/test/test_**optimizeopt.py >> --- a/pypy/jit/metainterp/**optimizeopt/test/test_**optimizeopt.py >> +++ b/pypy/jit/metainterp/**optimizeopt/test/test_**optimizeopt.py >> @@ -5837,3 +5837,30 @@ >> jump(i3, i4) >> """ >> self.optimize_loop(ops, expected) >> + >> + def test_forced_virtual_pure_**getfield(self): >> + ops = """ >> + [p0] >> + p1 = getfield_gc_pure(p0, descr=valuedescr) >> + jump(p1) >> + """ >> + self.optimize_loop(ops, ops) >> + >> + ops = """ >> + [p0] >> + p1 = new_with_vtable(ConstClass(**node_vtable)) >> + setfield_gc(p1, p0, descr=valuedescr) >> + escape(p1) >> + p2 = getfield_gc_pure(p1, descr=valuedescr) >> + escape(p2) >> + jump(p0) >> + """ >> + expected = """ >> + [p0] >> + p1 = new_with_vtable(ConstClass(**node_vtable)) >> + setfield_gc(p1, p0, descr=valuedescr) >> + escape(p1) >> + escape(p0) >> + jump(p0) >> + """ >> + self.optimize_loop(ops, expected) >> \ No newline at end of file >> diff --git a/pypy/jit/metainterp/**optimizeopt/virtualize.py >> b/pypy/jit/metainterp/**optimizeopt/virtualize.py >> --- a/pypy/jit/metainterp/**optimizeopt/virtualize.py >> +++ b/pypy/jit/metainterp/**optimizeopt/virtualize.py >> @@ -20,6 +20,9 @@ >> self.source_op = source_op # the NEW_WITH_VTABLE/NEW_ARRAY >> operation >> # that builds this box >> >> + def is_forced_virtual(self): >> + return self.box is not None >> + >> def get_key_box(self): >> if self.box is None: >> return self.keybox >> @@ -120,7 +123,6 @@ >> op = ResOperation(rop.SETFIELD_GC, [box, subbox], None, >> descr=ofs) >> newoperations.append(op) >> - self._fields = None >> >> def _get_field_descr_list(self): >> _cached_sorted_fields = self._cached_sorted_fields >> @@ -351,7 +353,7 @@ >> if not self.optimizer.cpu.ts.CONST_**NULL.same_constant(objbox): >> seo(ResOperation(rop.SETFIELD_**GC, op.getarglist(), None, >> descr = vrefinfo.descr_forced)) >> - >> + >> # - set 'virtual_token' to TOKEN_NONE >> args = [op.getarg(0), ConstInt(vrefinfo.TOKEN_NONE)] >> seo(ResOperation(rop.SETFIELD_**GC, args, None, >> @@ -365,6 +367,14 @@ >> >> def optimize_GETFIELD_GC(self, op): >> value = self.getvalue(op.getarg(0)) >> + # If this is an immutable field (as indicated by >> op.is_always_pure()) >> + # then it's safe to reuse the virtual's field, even if it has >> been >> + # forced, because it should never be written to again. >> + if value.is_forced_virtual() and op.is_always_pure(): >> + fieldvalue = value.getfield(op.getdescr(), None) >> + if fieldvalue is not None: >> + self.make_equal_to(op.result, fieldvalue) >> + return >> if value.is_virtual(): >> assert isinstance(value, AbstractVirtualValue) >> fieldvalue = value.getfield(op.getdescr(), None) >> @@ -382,6 +392,7 @@ >> >> def optimize_SETFIELD_GC(self, op): >> value = self.getvalue(op.getarg(0)) >> + >> if value.is_virtual(): >> fieldvalue = self.getvalue(op.getarg(1)) >> value.setfield(op.getdescr(), fieldvalue) >> diff --git a/pypy/jit/metainterp/test/**test_dict.py >> b/pypy/jit/metainterp/test/**test_dict.py >> --- a/pypy/jit/metainterp/test/**test_dict.py >> +++ b/pypy/jit/metainterp/test/**test_dict.py >> @@ -130,6 +130,38 @@ >> assert res == 50 >> self.check_loops(int_mod=1) >> >> + def test_repeated_lookup(self): >> + myjitdriver = JitDriver(greens = [], reds = ['n', 'd']) >> + class Wrapper(object): >> + _immutable_fields_ = ["value"] >> + def __init__(self, value): >> + self.value = value >> + def eq_func(a, b): >> + return a.value == b.value >> + def hash_func(x): >> + return objectmodel.compute_hash(x.**value) >> + >> + def f(n): >> + d = None >> + while n> 0: >> + myjitdriver.jit_merge_point(n=**n, d=d) >> + d = objectmodel.r_dict(eq_func, hash_func) >> + y = Wrapper(str(n)) >> + d[y] = n - 1 >> + n = d[y] >> + return d[Wrapper(str(n + 1))] >> + >> + res = self.meta_interp(f, [100], listops=True) >> + assert res == f(50) >> + # XXX: ideally there would be 7 calls here, but repeated >> CALL_PURE with >> + # the same arguments are not folded, because we have conflicting >> + # definitions of pure, once strhash can be appropriately folded >> + # this should be decreased to seven. >> + self.check_loops({"call": 8, "guard_false": 1, >> "guard_no_exception": 5, >> + "guard_true": 1, "int_and": 1, "int_gt": 1, >> + "int_is_true": 1, "int_sub": 1, "jump": 1, >> + "new_with_vtable": 1, "setfield_gc": 1}) >> + >> >> class TestOOtype(DictTests, OOJitMixin): >> pass >> diff --git a/pypy/rpython/lltypesystem/**rstr.py >> b/pypy/rpython/lltypesystem/**rstr.py >> --- a/pypy/rpython/lltypesystem/**rstr.py >> +++ b/pypy/rpython/lltypesystem/**rstr.py >> @@ -323,6 +323,8 @@ >> return s >> ll_str2unicode.oopspec = 'str.str2unicode(str)' >> >> + # it's pure but it does not look like it >> + @purefunction >> def ll_strhash(s): >> # unlike CPython, there is no reason to avoid to return -1 >> # but our malloc initializes the memory to zero, so we use zero >> as the >> @@ -334,7 +336,6 @@ >> x = 29872897 >> s.hash = x >> return x >> - ll_strhash._pure_function_ = True # it's pure but it does not look >> like it >> >> def ll_strfasthash(s): >> return s.hash # assumes that the hash is already computed >> ______________________________**_________________ >> pypy-commit mailing list >> [email protected] >> http://mail.python.org/**mailman/listinfo/pypy-commit<http://mail.python.org/mailman/listinfo/pypy-commit> >> > > ______________________________**_________________ > pypy-commit mailing list > [email protected] > http://mail.python.org/**mailman/listinfo/pypy-commit<http://mail.python.org/mailman/listinfo/pypy-commit> > -- "I disapprove of what you say, but I will defend to the death your right to say it." -- Evelyn Beatrice Hall (summarizing Voltaire) "The people's good is the highest law." -- Cicero
_______________________________________________ pypy-commit mailing list [email protected] http://mail.python.org/mailman/listinfo/pypy-commit
