Author: Maciej Fijalkowski <fij...@gmail.com> Branch: Changeset: r45045:3f8617bb49eb Date: 2011-06-21 20:55 +0200 http://bitbucket.org/pypy/pypy/changeset/3f8617bb49eb/
Log: merge diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst --- a/pypy/doc/project-ideas.rst +++ b/pypy/doc/project-ideas.rst @@ -131,6 +131,18 @@ finder, which is nicely portable. So far it gives a pypy that is around 7% slower.) +Embedding PyPy +---------------------------------------- + +Being able to embed PyPy, say with its own limited C API, would be +useful. But here is the most interesting variant, straight from +EuroPython live discussion :-) We can have a generic "libpypy.so" that +can be used as a placeholder dynamic library, and when it gets loaded, +it runs a .py module that installs (via ctypes) the interface it wants +exported. This would give us a one-size-fits-all generic .so file to be +imported by any application that wants to load .so files :-) + + .. _`issue tracker`: http://bugs.pypy.org .. _`mailing list`: http://mail.python.org/mailman/listinfo/pypy-dev .. _`jitviewer`: http://bitbucket.org/pypy/jitviewer 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/module/imp/importing.py b/pypy/module/imp/importing.py --- a/pypy/module/imp/importing.py +++ b/pypy/module/imp/importing.py @@ -622,7 +622,13 @@ try: if find_info: w_mod = load_module(space, w_modulename, find_info) - w_mod = space.getitem(space.sys.get("modules"), w_modulename) + try: + w_mod = space.getitem(space.sys.get("modules"), + w_modulename) + except OperationError, oe: + if not oe.match(space, space.w_KeyError): + raise + raise OperationError(space.w_ImportError, w_modulename) if w_parent is not None: space.setattr(w_parent, space.wrap(partname), w_mod) return w_mod diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py --- a/pypy/module/imp/test/test_import.py +++ b/pypy/module/imp/test/test_import.py @@ -37,6 +37,7 @@ ambig = "imamodule = 1", test_reload = "def test():\n raise ValueError\n", infinite_reload = "import infinite_reload; reload(infinite_reload)", + del_sys_module = "import sys\ndel sys.modules['del_sys_module']\n", ) root.ensure("notapackage", dir=1) # empty, no __init__.py setuppkg("pkg", @@ -562,6 +563,14 @@ except ImportError: pass + def test_del_from_sys_modules(self): + try: + import del_sys_module + except ImportError: + pass # ok + else: + assert False, 'should not work' + class TestAbi: def test_abi_tag(self): space1 = gettestobjspace(soabi='TEST') diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -44,6 +44,10 @@ self.invalidates = [] def invalidated(self): + if self.invalidates: + self._invalidated() + + def _invalidated(self): for arr in self.invalidates: arr.force_if_needed() del self.invalidates[:] @@ -353,4 +357,4 @@ __div__ = interp2app(BaseArray.descr_div), mean = interp2app(BaseArray.descr_mean), -) \ No newline at end of file +) 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 diff --git a/pypy/translator/goal/translate.py b/pypy/translator/goal/translate.py --- a/pypy/translator/goal/translate.py +++ b/pypy/translator/goal/translate.py @@ -103,6 +103,8 @@ specname = os.path.splitext(os.path.basename(targetspec))[0] sys.path.insert(0, os.path.dirname(targetspec)) mod = __import__(specname) + if 'target' not in mod.__dict__: + raise Exception("file %r is not a valid targetxxx.py." % (targetspec,)) return mod.__dict__ def parse_options_and_load_target(): _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit