From commits-noreply at bitbucket.org Sun May 1 07:44:47 2011
From: commits-noreply at bitbucket.org (lac)
Date: Sun, 1 May 2011 07:44:47 +0200 (CEST)
Subject: [pypy-svn] pypy default: edit how to release to include changing
the tracker so we don't make that mistake again (no way for
people to file bugs against the new release)
Message-ID: <20110501054447.83FC136C207@codespeak.net>
Author: Laura Creighton
Branch:
Changeset: r43819:d5b7af1357f8
Date: 2011-05-01 07:44 +0200
http://bitbucket.org/pypy/pypy/changeset/d5b7af1357f8/
Log: edit how to release to include changing the tracker so we don't make
that mistake again (no way for people to file bugs against the new
release)
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -31,6 +31,7 @@
necessary
* update pypy/doc/contributor.txt (and possibly LICENSE)
* update README
+* change the tracker to have a new release tag to file bugs against
* go to pypy/tool/release and run:
force-builds.py /release/
* wait for builds to complete, make sure there are no failures
From commits-noreply at bitbucket.org Sun May 1 09:36:33 2011
From: commits-noreply at bitbucket.org (lac)
Date: Sun, 1 May 2011 09:36:33 +0200 (CEST)
Subject: [pypy-svn] pypy default: typo
Message-ID: <20110501073633.88D1F36C208@codespeak.net>
Author: Laura Creighton
Branch:
Changeset: r43820:1a811cae33cd
Date: 2011-05-01 09:36 +0200
http://bitbucket.org/pypy/pypy/changeset/1a811cae33cd/
Log: typo
diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -171,7 +171,7 @@
using only the tools provided by the Microsoft .NET SDK, since
``ilasm`` crashes when trying to assemble the pypy-cli code due to its
size. Microsoft .NET SDK 2.0.50727.42 is affected by this bug; other
-version could be affected as well: if you find a version of the SDK
+versions could be affected as well: if you find a version of the SDK
that works, please tell us.
Windows users that want to compile their own pypy-cli can install
From commits-noreply at bitbucket.org Sun May 1 11:21:10 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 11:21:10 +0200 (CEST)
Subject: [pypy-svn] pypy default: Kill these tests. They should have been
removed by the merge
Message-ID: <20110501092110.60AA836C208@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43821:33350df8a569
Date: 2011-05-01 11:20 +0200
http://bitbucket.org/pypy/pypy/changeset/33350df8a569/
Log: Kill these tests. They should have been removed by the merge of
post-release-1.5... not sure I understand why they stayed around.
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -131,25 +131,6 @@
assert self.space.eq_w(space.call_function(get, w("33")), w(None))
assert self.space.eq_w(space.call_function(get, w("33"), w(44)), w(44))
- def test_initialize_from_strdict_shared(self):
- space = self.space
- w = space.wrap
- d = {"a": w(1), "b": w(2)}
- w_d = space.newdict(from_strdict_shared=d)
- assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
- assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
-
- def test_initialize_from_strdict_really_shared(self):
- space = self.space
- w = space.wrap
- d = {"a": w(1), "b": w(2)}
- w_d = space.newdict(from_strdict_shared=d)
- assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
- assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
- d["c"] = w(41)
- assert self.space.eq_w(space.getitem(w_d, w("c")), w(41))
-
-
class AppTest_DictObject:
def setup_class(cls):
From commits-noreply at bitbucket.org Sun May 1 12:55:20 2011
From: commits-noreply at bitbucket.org (l.diekmann)
Date: Sun, 1 May 2011 12:55:20 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: today's planning
Message-ID: <20110501105520.58F7936C210@codespeak.net>
Author: Lukas Diekmann
Branch: extradoc
Changeset: r3549:b004b3610d97
Date: 2011-05-01 12:55 +0200
http://bitbucket.org/pypy/extradoc/changeset/b004b3610d97/
Log: today's planning
diff --git a/sprintinfo/gothenburg-2011/planning.txt b/sprintinfo/gothenburg-2011/planning.txt
--- a/sprintinfo/gothenburg-2011/planning.txt
+++ b/sprintinfo/gothenburg-2011/planning.txt
@@ -1,51 +1,35 @@
people present:
- Armin
- - Carl Friedrich
- Laura
- Lukas
- - Anders
- Romain
- Dario
- - Kristján
- - Anto
-
tasks:
-- release 1.5
- - merge in 2.7.1 stuff DONE
- - documentation (Anto, Laura) MORE PROGRESS
- - document minimark DONE
- - document __builtins__ behaviour in cpython-differences
- - mercurial in the coding-guide (Anto)
- - release announcement (Anto, Carl Friedrich)
- - look at the tracker
- - start the Mac build (Dario, Romain)
- - investigate Mac problems DONE?
- - find out whether cProfile is giving interesting information (Anto, Lukas)
- - add a warning about Windows 64 (Kristján, Carl Friedrich) SHOULD-BE-PUSHED
- - do a full build on Windows (Armin, Kristján)
-
-- discuss stackless+jit integration HAPPENED
-- discuss embedding issues HAPPENED
-- start playing with stack slicing (Armin, Kristján)
+- release 1.5 DONE
+- start playing with stack slicing (Armin, Kristján) STARTED
- branches to be integrated/finished afterwards
- 32-on-64
- - lukas' branches: list-strategies/dict-strategies
- - new-dict-proxy READY
- - merge new-dict-proxy into post-release (Lukas) DONE
- - out-of-line guards
- - refactor-not-in-translator
- - håkan's branches
+ - lukas' branches: list-strategies/dict-strategies TALK WITH CARL-FRIEDRICH
+ - lukas' branches: set-object (lukas) IN PROGRESS
+ - out-of-line guards TO BE MERGED
+ - refactor-not-in-translator READY?
+ - håkan's branches NEEDS TESTS
- jitypes2
- other tasks
- - look into cython (Armin, Romain, Dario) FORK + BASIC ARCH HAPPENED
- - investigate Open End software on top of PyPy EASIER THAN FEARED
+ - look into cython
+ - investigate Open End software on top of PyPy DONE
- (feedback to wesley chun's paragraphs: Armin, Laura)
- presentations/discussions
- - Lukas' presentation on memory improvements DONE
- - what are håkan's branches doing? DONE
+ - what are håkan's branches doing? WHERE ARE THE SLIDES?
- codespeak migration
+ - save files: see codespeak doc
+ - mailinglists: python.org
+ - pypy.org
+ - where to store builds, releases?
+ - buildbot
+ - issue tracker: OpenEnd investigate?
- EuroPython keynote/training (Anto, Armin)
From commits-noreply at bitbucket.org Sun May 1 13:14:47 2011
From: commits-noreply at bitbucket.org (berdario)
Date: Sun, 1 May 2011 13:14:47 +0200 (CEST)
Subject: [pypy-svn] pypy default: Fix test: we don't keep anymore .rst files
inside doc/config
Message-ID: <20110501111447.8598D36C208@codespeak.net>
Author: Dario Bertini
Branch:
Changeset: r43822:f26b65b41ef5
Date: 2011-05-01 13:13 +0200
http://bitbucket.org/pypy/pypy/changeset/f26b65b41ef5/
Log: Fix test: we don't keep anymore .rst files inside doc/config
diff --git a/pypy/config/test/test_pypyoption.py b/pypy/config/test/test_pypyoption.py
--- a/pypy/config/test/test_pypyoption.py
+++ b/pypy/config/test/test_pypyoption.py
@@ -70,6 +70,6 @@
prefix = descr._name
c = Config(descr)
for path in c.getpaths(include_groups=True):
- fn = prefix + "." + path + ".rst"
+ fn = prefix + "." + path + ".txt"
yield check_file_exists, fn
From commits-noreply at bitbucket.org Sun May 1 13:14:48 2011
From: commits-noreply at bitbucket.org (berdario)
Date: Sun, 1 May 2011 13:14:48 +0200 (CEST)
Subject: [pypy-svn] pypy default: merge heads
Message-ID: <20110501111448.92C5136C208@codespeak.net>
Author: Dario Bertini
Branch:
Changeset: r43823:08aacc7a27f5
Date: 2011-05-01 13:14 +0200
http://bitbucket.org/pypy/pypy/changeset/08aacc7a27f5/
Log: merge heads
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -131,25 +131,6 @@
assert self.space.eq_w(space.call_function(get, w("33")), w(None))
assert self.space.eq_w(space.call_function(get, w("33"), w(44)), w(44))
- def test_initialize_from_strdict_shared(self):
- space = self.space
- w = space.wrap
- d = {"a": w(1), "b": w(2)}
- w_d = space.newdict(from_strdict_shared=d)
- assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
- assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
-
- def test_initialize_from_strdict_really_shared(self):
- space = self.space
- w = space.wrap
- d = {"a": w(1), "b": w(2)}
- w_d = space.newdict(from_strdict_shared=d)
- assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
- assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
- d["c"] = w(41)
- assert self.space.eq_w(space.getitem(w_d, w("c")), w(41))
-
-
class AppTest_DictObject:
def setup_class(cls):
From commits-noreply at bitbucket.org Sun May 1 14:18:05 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 14:18:05 +0200 (CEST)
Subject: [pypy-svn] pypy default: The failing test reported by issue704
Message-ID: <20110501121805.0E49A36C201@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43824:88473debb6ed
Date: 2011-05-01 13:38 +0200
http://bitbucket.org/pypy/pypy/changeset/88473debb6ed/
Log: The failing test reported by issue704
diff --git a/pypy/rlib/rsre/test/test_match.py b/pypy/rlib/rsre/test/test_match.py
--- a/pypy/rlib/rsre/test/test_match.py
+++ b/pypy/rlib/rsre/test/test_match.py
@@ -283,3 +283,7 @@
def test_match_bug2(self):
r = get_code(r'(x??)??$')
assert rsre_core.match(r, "x")
+
+ def test_match_bug3(self):
+ r = get_code(r'([ax]*?x*)?$')
+ assert rsre_core.match(r, "aaxaa")
From commits-noreply at bitbucket.org Sun May 1 14:18:06 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 14:18:06 +0200 (CEST)
Subject: [pypy-svn] pypy default: Fix for issue704.
Message-ID: <20110501121806.2C68B36C201@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43825:8b96406482dd
Date: 2011-05-01 14:17 +0200
http://bitbucket.org/pypy/pypy/changeset/8b96406482dd/
Log: Fix for issue704.
diff --git a/pypy/rlib/rsre/rsre_core.py b/pypy/rlib/rsre/rsre_core.py
--- a/pypy/rlib/rsre/rsre_core.py
+++ b/pypy/rlib/rsre/rsre_core.py
@@ -227,11 +227,12 @@
subresult = None
def move_to_next_result(self, ctx):
+ # returns either 'self' or None
result = self.subresult
if result is None:
return
if result.move_to_next_result(ctx):
- return result
+ return self
return self.find_next_result(ctx)
def find_next_result(self, ctx):
From commits-noreply at bitbucket.org Sun May 1 14:18:08 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 14:18:08 +0200 (CEST)
Subject: [pypy-svn] pypy default: merge heads
Message-ID: <20110501121808.BE8A236C214@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43826:e85747858f2c
Date: 2011-05-01 14:17 +0200
http://bitbucket.org/pypy/pypy/changeset/e85747858f2c/
Log: merge heads
diff --git a/pypy/rlib/rsre/rsre_core.py b/pypy/rlib/rsre/rsre_core.py
--- a/pypy/rlib/rsre/rsre_core.py
+++ b/pypy/rlib/rsre/rsre_core.py
@@ -227,11 +227,12 @@
subresult = None
def move_to_next_result(self, ctx):
+ # returns either 'self' or None
result = self.subresult
if result is None:
return
if result.move_to_next_result(ctx):
- return result
+ return self
return self.find_next_result(ctx)
def find_next_result(self, ctx):
diff --git a/pypy/rlib/rsre/test/test_match.py b/pypy/rlib/rsre/test/test_match.py
--- a/pypy/rlib/rsre/test/test_match.py
+++ b/pypy/rlib/rsre/test/test_match.py
@@ -283,3 +283,7 @@
def test_match_bug2(self):
r = get_code(r'(x??)??$')
assert rsre_core.match(r, "x")
+
+ def test_match_bug3(self):
+ r = get_code(r'([ax]*?x*)?$')
+ assert rsre_core.match(r, "aaxaa")
From commits-noreply at bitbucket.org Sun May 1 14:32:53 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 14:32:53 +0200 (CEST)
Subject: [pypy-svn] pypy default: Fix for test/test_setobject.py.
Message-ID: <20110501123253.9D4C736C205@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43827:e9455a0ff967
Date: 2011-05-01 14:32 +0200
http://bitbucket.org/pypy/pypy/changeset/e9455a0ff967/
Log: Fix for test/test_setobject.py.
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -37,13 +37,16 @@
#return space.call(space.type(w_self),W_SetIterObject(rdict_w))
objtype = type(w_self)
if objtype is W_SetObject:
- obj = W_SetObject(space, rdict_w)
+ w_obj = W_SetObject(space, rdict_w)
elif objtype is W_FrozensetObject:
- obj = W_FrozensetObject(space, rdict_w)
+ w_obj = W_FrozensetObject(space, rdict_w)
else:
- itemiterator = space.iter(W_SetIterObject(rdict_w))
- obj = space.call_function(space.type(w_self),itemiterator)
- return obj
+ w_type = space.type(w_self)
+ _, w_newdescr = w_type.lookup_where('__new__')
+ w_newfunc = space.get(w_newdescr, w_type)
+ w_itemiterator = W_SetIterObject(rdict_w)
+ w_obj = space.call_function(w_newfunc, w_type, w_itemiterator)
+ return w_obj
_lifeline_ = None
def getweakref(self):
From commits-noreply at bitbucket.org Sun May 1 15:51:25 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Sun, 1 May 2011 15:51:25 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: cleaned up inlining of
start_resumedescr into short preamble
Message-ID: <20110501135125.B5DF236C206@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43828:f93eceb81795
Date: 2011-04-27 20:11 +0200
http://bitbucket.org/pypy/pypy/changeset/f93eceb81795/
Log: cleaned up inlining of start_resumedescr into short preamble
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -201,6 +201,8 @@
for a in snapshot_args:
if not isinstance(a, Const):
a = loop.preamble.inputargs[jump_args.index(a)]
+ a = self.inliner.inline_arg(a)
+ a = self.getvalue(a).get_key_box()
new_snapshot_args.append(a)
snapshot.boxes = new_snapshot_args
snapshot = snapshot.prev
@@ -209,20 +211,6 @@
if short:
assert short[-1].getopnum() == rop.JUMP
short[-1].setdescr(loop.token)
- if False:
- # FIXME: This should save some memory but requires
- # a lot of tests to be fixed...
- loop.preamble.operations = short[:]
-
- # FIXME: combine with snapshot loop above
- short_resumedescr = start_resumedescr.clone_if_mutable()
- assert isinstance(short_resumedescr, ResumeGuardDescr)
- self.inliner.inline_descr_inplace(short_resumedescr)
- snapshot = short_resumedescr.rd_snapshot
- while snapshot:
- snapshot.boxes = [self.getvalue(b).get_key_box()
- for b in snapshot.boxes]
- snapshot = snapshot.prev
# Turn guards into conditional jumps to the preamble
for i in range(len(short)):
@@ -230,7 +218,7 @@
if op.is_guard():
op = op.clone()
op.setfailargs(None)
- descr = short_resumedescr.clone_if_mutable()
+ descr = start_resumedescr.clone_if_mutable()
op.setdescr(descr)
short[i] = op
@@ -246,7 +234,7 @@
short_loop.inputargs = newargs
ops = [inliner.inline_op(op) for op in short_loop.operations]
short_loop.operations = ops
- descr = short_resumedescr.clone_if_mutable()
+ descr = start_resumedescr.clone_if_mutable()
inliner.inline_descr_inplace(descr)
short_loop.start_resumedescr = descr
From commits-noreply at bitbucket.org Sun May 1 17:39:50 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 17:39:50 +0200 (CEST)
Subject: [pypy-svn] pypy.org extradoc: Kill a mention of svn.
Message-ID: <20110501153950.D72E936C206@codespeak.net>
Author: Armin Rigo
Branch: extradoc
Changeset: r185:acb4f3049c60
Date: 2011-05-01 14:34 +0200
http://bitbucket.org/pypy/pypy.org/changeset/acb4f3049c60/
Log: Kill a mention of svn.
diff --git a/download.html b/download.html
--- a/download.html
+++ b/download.html
@@ -112,7 +112,7 @@
Building from source
Get the source code. The following packages contain the source at
-the same revision as the above binaries (these are svn exports):
+the same revision as the above binaries:
- pypy-1.5-src.tar.bz2 (sources, Unix line endings)
- pypy-1.5-src.zip (sources, Windows line endings) not available
diff --git a/source/download.txt b/source/download.txt
--- a/source/download.txt
+++ b/source/download.txt
@@ -98,7 +98,7 @@
-------------------------------
1. Get the source code. The following packages contain the source at
- the same revision as the above binaries (these are svn exports):
+ the same revision as the above binaries:
* `pypy-1.5-src.tar.bz2`__ (sources, Unix line endings)
* pypy-1.5-src.zip (sources, Windows line endings) not available
From commits-noreply at bitbucket.org Sun May 1 17:39:51 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 17:39:51 +0200 (CEST)
Subject: [pypy-svn] pypy.org extradoc: merge heads
Message-ID: <20110501153951.007F836C206@codespeak.net>
Author: Armin Rigo
Branch: extradoc
Changeset: r186:cfeab31f3304
Date: 2011-05-01 17:39 +0200
http://bitbucket.org/pypy/pypy.org/changeset/cfeab31f3304/
Log: merge heads
diff --git a/source/index.txt b/source/index.txt
--- a/source/index.txt
+++ b/source/index.txt
@@ -3,8 +3,8 @@
title: PyPy
---
-PyPy is a `very compliant`_ implementation of the `Python`_ language (2.7.1).
-PyPy has several advantages and distinctive features:
+PyPy is a `fast`_, `compliant`_ alternative implementation of the `Python`_
+language (2.7.1). It has several advantages and distinct features:
* **Speed:** thanks to its Just-in-Time compiler, Python programs
often run `faster`_ on PyPy. `(What is a JIT compiler?)`_
@@ -18,6 +18,10 @@
* **Stackless:** PyPy can be configured to run in `stackless`_ mode,
providing micro-threads for massive concurrency.
+ * **Compatibility:** PyPy is `highly compatible`_ with existing python code.
+ It supports `ctypes`_ and can run popular python libraries like `twisted`_
+ and `django`_.
+
* As well as other `features`_.
.. class:: download
@@ -26,20 +30,22 @@
.. __: download.html
-To read more about Python, look into `Python docs`_ and check our
-Compatibility_ page. PyPy can run such python libraries as `twisted`_
-and `django`_ and supports `ctypes`_.
+Want to know more? A good place to start is our detailed `speed`_ and
+`compatibility`_ reports!
.. _`stackless`: http://www.stackless.com/
.. _`Python`: http://python.org/
+.. _`fast`: http://speed.pypy.org/
.. _`faster`: http://speed.pypy.org/
.. _`(What is a JIT compiler?)`: http://en.wikipedia.org/wiki/Just-in-time_compilation
.. _`run untrusted code`: features.html#sandboxing
-.. _`very compliant`: compat.html
+.. _`compliant`: compat.html
.. _`Python docs`: http://docs.python.org/release/2.7.1/
.. _`twisted`: http://twistedmatrix.com/
.. _`django`: http://www.djangoproject.com/
.. _`ctypes`: http://docs.python.org/release/2.7.1/library/ctypes.html
.. _`features`: features.html
.. _`less space`: http://morepypy.blogspot.com/2009/10/gc-improvements.html
-.. _Compatibility: compat.html
+.. _`highly compatible`: compat.html
+.. _`speed`: http://speed.pypy.org/
+.. _`compatibility`: compat.html
From commits-noreply at bitbucket.org Sun May 1 18:06:29 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Sun, 1 May 2011 18:06:29 +0200 (CEST)
Subject: [pypy-svn] pypy default: Merged upstream.
Message-ID: <20110501160629.7F09536C206@codespeak.net>
Author: Alex Gaynor
Branch:
Changeset: r43829:4221c94d7fb4
Date: 2011-05-01 11:54 -0400
http://bitbucket.org/pypy/pypy/changeset/4221c94d7fb4/
Log: Merged upstream.
diff --git a/pypy/rlib/rsre/rsre_core.py b/pypy/rlib/rsre/rsre_core.py
--- a/pypy/rlib/rsre/rsre_core.py
+++ b/pypy/rlib/rsre/rsre_core.py
@@ -809,7 +809,7 @@
def fre(ctx, ptr, end, ppos):
return end
elif checkerfn == match_IN:
- install_jitdriver_spec('MatchIn',
+ install_jitdriver_spec('MatchIn',
greens=['ppos', 'ctx.pattern'],
reds=['ptr', 'end', 'ctx'],
debugprint=(1, 0))
@@ -823,7 +823,7 @@
else:
return ptr
elif checkerfn == match_IN_IGNORE:
- install_jitdriver_spec('MatchInIgnore',
+ install_jitdriver_spec('MatchInIgnore',
greens=['ppos', 'ctx.pattern'],
reds=['ptr', 'end', 'ctx'],
debugprint=(1, 0))
From commits-noreply at bitbucket.org Sun May 1 18:06:31 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Sun, 1 May 2011 18:06:31 +0200 (CEST)
Subject: [pypy-svn] pypy default: Implement ll_math_isfinite in the CLI
backend.
Message-ID: <20110501160631.14F6C282B5B@codespeak.net>
Author: Alex Gaynor
Branch:
Changeset: r43830:7880b66aef80
Date: 2011-05-01 12:06 -0400
http://bitbucket.org/pypy/pypy/changeset/7880b66aef80/
Log: Implement ll_math_isfinite in the CLI backend.
diff --git a/pypy/translator/cli/src/ll_math.cs b/pypy/translator/cli/src/ll_math.cs
--- a/pypy/translator/cli/src/ll_math.cs
+++ b/pypy/translator/cli/src/ll_math.cs
@@ -25,13 +25,13 @@
return result;
}
- // the following code is borrowed from
+ // the following code is borrowed from
// http://web.telia.com/~u31115556/under_construction/Functions.Cephes.CFunctions.cs
const double MAXNUM = double.MaxValue; // 1.79769313486232e308
const int MEXP = 0x7ff;
[StructLayout(LayoutKind.Explicit)] //, CLSCompliantAttribute(false)]
- struct DoubleUshorts
+ struct DoubleUshorts
{
[FieldOffset(0)] public double d;
[FieldOffset(0)] public ushort u0;
@@ -235,6 +235,11 @@
return double.IsInfinity(x);
}
+ static public bool ll_math_isfinite(double x)
+ {
+ return !double.IsNaN(x) && !double.IsInfinity(x);
+ }
+
static public double ll_math_copysign(double x, double y)
{
if (x < 0.0)
From commits-noreply at bitbucket.org Sun May 1 18:21:02 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Sun, 1 May 2011 18:21:02 +0200 (CEST)
Subject: [pypy-svn] pypy default: Implement isfinite on the JVM.
Message-ID: <20110501162102.3FCAE36C206@codespeak.net>
Author: Alex Gaynor
Branch:
Changeset: r43831:0d638ceaf7c4
Date: 2011-05-01 16:21 +0000
http://bitbucket.org/pypy/pypy/changeset/0d638ceaf7c4/
Log: Implement isfinite on the JVM.
diff --git a/pypy/translator/jvm/src/pypy/PyPy.java b/pypy/translator/jvm/src/pypy/PyPy.java
--- a/pypy/translator/jvm/src/pypy/PyPy.java
+++ b/pypy/translator/jvm/src/pypy/PyPy.java
@@ -1198,6 +1198,10 @@
return Double.isInfinite(x);
}
+ public boolean ll_math_isfinite(double x) {
+ return !Double.isNaN(x) && !Double.isInfinite(x);
+ }
+
private double check(double v) {
if (Double.isNaN(v))
interlink.throwValueError();
From commits-noreply at bitbucket.org Sun May 1 19:15:45 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 19:15:45 +0200 (CEST)
Subject: [pypy-svn] pypy.org extradoc: Rename the link "Dev Site" into
"Dev Documentation" and regenerate.
Message-ID: <20110501171545.B9E22282B59@codespeak.net>
Author: Armin Rigo
Branch: extradoc
Changeset: r187:b0ff4e10f01e
Date: 2011-05-01 19:15 +0200
http://bitbucket.org/pypy/pypy.org/changeset/b0ff4e10f01e/
Log: Rename the link "Dev Site" into "Dev Documentation" and regenerate.
diff --git a/compat.html b/compat.html
--- a/compat.html
+++ b/compat.html
@@ -40,7 +40,7 @@
-->
-
+
diff --git a/download.html b/download.html
--- a/download.html
+++ b/download.html
@@ -40,7 +40,7 @@
-->
-
+
diff --git a/index.html b/index.html
--- a/index.html
+++ b/index.html
@@ -40,15 +40,15 @@
-->
-
+
diff --git a/contact.html b/contact.html
--- a/contact.html
+++ b/contact.html
@@ -40,7 +40,7 @@
-->
-
+
diff --git a/archive.html b/archive.html
--- a/archive.html
+++ b/archive.html
@@ -40,7 +40,7 @@
-->
-
+
diff --git a/features.html b/features.html
--- a/features.html
+++ b/features.html
@@ -40,7 +40,7 @@
-->
-
+
From commits-noreply at bitbucket.org Sun May 1 19:16:51 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 19:16:51 +0200 (CEST)
Subject: [pypy-svn] pypy.org extradoc: Move this paragraph higher,
before the "optional" items.
Message-ID: <20110501171651.E5C8B282B59@codespeak.net>
Author: Armin Rigo
Branch: extradoc
Changeset: r188:7ddbc7bea99c
Date: 2011-05-01 19:16 +0200
http://bitbucket.org/pypy/pypy.org/changeset/7ddbc7bea99c/
Log: Move this paragraph higher, before the "optional" items.
diff --git a/index.html b/index.html
--- a/index.html
+++ b/index.html
@@ -55,13 +55,13 @@
often run faster on PyPy. (What is a JIT compiler?)
Memory usage: large, memory-hungry Python programs might end up
taking less space than they do in CPython.
+Compatibility: PyPy is highly compatible with existing python code.
+It supports ctypes and can run popular python libraries like twisted
+and django.
Sandboxing: PyPy provides the ability to run untrusted code in a
fully secure way.
Stackless: PyPy can be configured to run in stackless mode,
providing micro-threads for massive concurrency.
-Compatibility: PyPy is highly compatible with existing python code.
-It supports ctypes and can run popular python libraries like twisted
-and django.
As well as other features.
diff --git a/source/index.txt b/source/index.txt
--- a/source/index.txt
+++ b/source/index.txt
@@ -12,16 +12,16 @@
* **Memory usage:** large, memory-hungry Python programs might end up
taking `less space`_ than they do in CPython.
+ * **Compatibility:** PyPy is `highly compatible`_ with existing python code.
+ It supports `ctypes`_ and can run popular python libraries like `twisted`_
+ and `django`_.
+
* **Sandboxing:** PyPy provides the ability to `run untrusted code`_ in a
fully secure way.
* **Stackless:** PyPy can be configured to run in `stackless`_ mode,
providing micro-threads for massive concurrency.
- * **Compatibility:** PyPy is `highly compatible`_ with existing python code.
- It supports `ctypes`_ and can run popular python libraries like `twisted`_
- and `django`_.
-
* As well as other `features`_.
.. class:: download
From commits-noreply at bitbucket.org Sun May 1 19:25:59 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 19:25:59 +0200 (CEST)
Subject: [pypy-svn] pypy.org extradoc: Points to readthedocs.org instead of
codespeak.net.
Message-ID: <20110501172559.ABC12282B59@codespeak.net>
Author: Armin Rigo
Branch: extradoc
Changeset: r189:794157895326
Date: 2011-05-01 19:25 +0200
http://bitbucket.org/pypy/pypy.org/changeset/794157895326/
Log: Points to readthedocs.org instead of codespeak.net.
diff --git a/compat.html b/compat.html
--- a/compat.html
+++ b/compat.html
@@ -40,7 +40,7 @@
-->
-
+
@@ -99,7 +99,7 @@
won't work.
-
A more complete list is available at our dev site.
+
A more complete list is available at our dev site.
-->
-
+
@@ -123,7 +123,7 @@
hg clone http://bitbucket.org/pypy/pypy
-
Make sure you installed the dependencies. See the list here.
+Make sure you installed the dependencies. See the list here.
Enter the goal directory:
@@ -157,7 +157,7 @@
is delicate. It requires using either MSVC or gcc with no particularly
fancy options. It does not work e.g. with clang, or if you pass uncommon
options with the CFLAGS environment variable. You can also try to
-compile PyPy with the shadow stack option.
+compile PyPy with the
shadow stack option.
diff --git a/index.html b/index.html
--- a/index.html
+++ b/index.html
@@ -40,7 +40,7 @@
-->
-
+
diff --git a/source/_layouts/site.genshi b/source/_layouts/site.genshi
--- a/source/_layouts/site.genshi
+++ b/source/_layouts/site.genshi
@@ -9,7 +9,7 @@
('Download', 'download.html'),
('Compatibility', 'compat.html'),
('Performance', 'http://speed.pypy.org'),
- ('Dev Documentation', 'http://codespeak.net/pypy/trunk/pypy/doc/index.html'),
+ ('Dev Documentation', 'http://pypy.readthedocs.org/'),
('Blog', 'http://morepypy.blogspot.com'),
('Contact', 'contact.html'),
],
diff --git a/howtohelp.html b/howtohelp.html
--- a/howtohelp.html
+++ b/howtohelp.html
@@ -40,7 +40,7 @@
-->
-
+
diff --git a/source/compat.txt b/source/compat.txt
--- a/source/compat.txt
+++ b/source/compat.txt
@@ -86,4 +86,4 @@
.. _`CPython C API`: http://docs.python.org/c-api/
.. _`standard library modules`: http://docs.python.org/library/
-.. _`our dev site`: http://codespeak.net/pypy/trunk/pypy/doc/cpython_differences.html
+.. _`our dev site`: http://readthedocs.org/docs/pypy/en/latest/cpython_differences.html
diff --git a/contact.html b/contact.html
--- a/contact.html
+++ b/contact.html
@@ -40,7 +40,7 @@
-->
-
+
diff --git a/source/features.txt b/source/features.txt
--- a/source/features.txt
+++ b/source/features.txt
@@ -60,11 +60,11 @@
directory at all.
To read more about its features, try ``pypy_interact.py --help`` or go to
-`our dev site`_.
+`our documentation site`_.
.. _`pypy-sandbox`: download.html#sandboxed-version
.. _`full sources`: download.html#translate
-.. _`our dev site`: http://codespeak.net/pypy/trunk/pypy/doc/sandbox.html
+.. _`our documentation site`: http://readthedocs.org/docs/pypy/en/latest/sandbox.html
Stackless
diff --git a/source/download.txt b/source/download.txt
--- a/source/download.txt
+++ b/source/download.txt
@@ -112,7 +112,7 @@
2. Make sure you installed the dependencies. See the list here__.
- .. __: http://codespeak.net/pypy/trunk/pypy/doc/getting-started-python.html#translating-the-pypy-python-interpreter
+ .. __: http://readthedocs.org/docs/pypy/en/latest/getting-started-python.html#translating-the-pypy-python-interpreter
3. Enter the ``goal`` directory::
@@ -155,7 +155,7 @@
.. _`greenlets`: http://codespeak.net/svn/greenlet/trunk/doc/greenlet.txt
.. _Mercurial: http://mercurial.selenic.com/
.. _`nightly binary builds`: http://buildbot.pypy.org/nightly/trunk/
-.. _`shadow stack`: http://codespeak.net/pypy/trunk/pypy/doc/config/translation.gcrootfinder.html
+.. _`shadow stack`: http://readthedocs.org/docs/pypy/en/latest/config/translation.gcrootfinder.html
Checksums
---------
diff --git a/archive.html b/archive.html
--- a/archive.html
+++ b/archive.html
@@ -40,7 +40,7 @@
-->
-
+
diff --git a/features.html b/features.html
--- a/features.html
+++ b/features.html
@@ -40,7 +40,7 @@
-->
-
+
@@ -85,7 +85,7 @@
filesystem. You don't have to put
untrusted.py in the real
/tmp
directory at all.
To read more about its features, try pypy_interact.py --help or go to
-our dev site.
+
our documentation site.
Stackless
From commits-noreply at bitbucket.org Sun May 1 19:29:56 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 19:29:56 +0200 (CEST)
Subject: [pypy-svn] pypy.org extradoc: Use the shorter,
and maybe more official, links.
Message-ID: <20110501172956.7222D282B59@codespeak.net>
Author: Armin Rigo
Branch: extradoc
Changeset: r190:9809bbf62da5
Date: 2011-05-01 19:29 +0200
http://bitbucket.org/pypy/pypy.org/changeset/9809bbf62da5/
Log: Use the shorter, and maybe more official, links.
diff --git a/source/compat.txt b/source/compat.txt
--- a/source/compat.txt
+++ b/source/compat.txt
@@ -86,4 +86,4 @@
.. _`CPython C API`: http://docs.python.org/c-api/
.. _`standard library modules`: http://docs.python.org/library/
-.. _`our dev site`: http://readthedocs.org/docs/pypy/en/latest/cpython_differences.html
+.. _`our dev site`: http://pypy.readthedocs.org/en/latest/cpython_differences.html
diff --git a/source/features.txt b/source/features.txt
--- a/source/features.txt
+++ b/source/features.txt
@@ -64,7 +64,7 @@
.. _`pypy-sandbox`: download.html#sandboxed-version
.. _`full sources`: download.html#translate
-.. _`our documentation site`: http://readthedocs.org/docs/pypy/en/latest/sandbox.html
+.. _`our documentation site`: http://pypy.readthedocs.org/en/latest/sandbox.html
Stackless
diff --git a/source/download.txt b/source/download.txt
--- a/source/download.txt
+++ b/source/download.txt
@@ -112,7 +112,7 @@
2. Make sure you installed the dependencies. See the list here__.
- .. __: http://readthedocs.org/docs/pypy/en/latest/getting-started-python.html#translating-the-pypy-python-interpreter
+ .. __: http://pypy.readthedocs.org/en/latest/getting-started-python.html#translating-the-pypy-python-interpreter
3. Enter the ``goal`` directory::
@@ -155,7 +155,7 @@
.. _`greenlets`: http://codespeak.net/svn/greenlet/trunk/doc/greenlet.txt
.. _Mercurial: http://mercurial.selenic.com/
.. _`nightly binary builds`: http://buildbot.pypy.org/nightly/trunk/
-.. _`shadow stack`: http://readthedocs.org/docs/pypy/en/latest/config/translation.gcrootfinder.html
+.. _`shadow stack`: http://pypy.readthedocs.org/en/latest/config/translation.gcrootfinder.html
Checksums
---------
From commits-noreply at bitbucket.org Sun May 1 19:29:58 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 1 May 2011 19:29:58 +0200 (CEST)
Subject: [pypy-svn] pypy.org extradoc: Regen.
Message-ID: <20110501172958.89EA32A202C@codespeak.net>
Author: Armin Rigo
Branch: extradoc
Changeset: r191:e2520775a053
Date: 2011-05-01 19:29 +0200
http://bitbucket.org/pypy/pypy.org/changeset/e2520775a053/
Log: Regen.
diff --git a/compat.html b/compat.html
--- a/compat.html
+++ b/compat.html
@@ -99,7 +99,7 @@
won't work.
-A more complete list is available at our dev site.
+A more complete list is available at our dev site.
diff --git a/features.html b/features.html
--- a/features.html
+++ b/features.html
@@ -85,7 +85,7 @@
filesystem. You don't have to put
untrusted.py in the real
/tmp
directory at all.
To read more about its features, try pypy_interact.py --help or go to
-our documentation site.
+
our documentation site.
Stackless
From commits-noreply at bitbucket.org Sun May 1 20:11:17 2011
From: commits-noreply at bitbucket.org (berdario)
Date: Sun, 1 May 2011 20:11:17 +0200 (CEST)
Subject: [pypy-svn] pypy default: Added failing test for issue 705 and
checks inside modified-2.7/sysconfig.py to avoid the problem
Message-ID: <20110501181117.9A95D36C206@codespeak.net>
Author: Dario Bertini
Branch:
Changeset: r43832:099a287513d0
Date: 2011-05-01 20:09 +0200
http://bitbucket.org/pypy/pypy/changeset/099a287513d0/
Log: Added failing test for issue 705 and checks inside
modified-2.7/sysconfig.py to avoid the problem
diff --git a/lib-python/modified-2.7/sysconfig.py b/lib-python/modified-2.7/sysconfig.py
--- a/lib-python/modified-2.7/sysconfig.py
+++ b/lib-python/modified-2.7/sysconfig.py
@@ -369,10 +369,11 @@
# patched up as well.
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
- flags = _CONFIG_VARS[key]
- flags = re.sub('-arch\s+\w+\s', ' ', flags)
- flags = flags + ' ' + arch
- _CONFIG_VARS[key] = flags
+ if key in _CONFIG_VARS:
+ flags = _CONFIG_VARS[key]
+ flags = re.sub('-arch\s+\w+\s', ' ', flags)
+ flags = flags + ' ' + arch
+ _CONFIG_VARS[key] = flags
# If we're on OSX 10.5 or later and the user tries to
# compiles an extension using an SDK that is not present
diff --git a/lib-python/modified-2.7/test/test_sysconfig.py b/lib-python/modified-2.7/test/test_sysconfig.py
--- a/lib-python/modified-2.7/test/test_sysconfig.py
+++ b/lib-python/modified-2.7/test/test_sysconfig.py
@@ -210,13 +210,22 @@
self.assertEqual(get_platform(), 'macosx-10.4-fat64')
- for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
+ for arch in ('ppc', 'i386', 'ppc64', 'x86_64'):
get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
'-dynamic -DNDEBUG -g -O3'%(arch,))
self.assertEqual(get_platform(), 'macosx-10.4-%s'%(arch,))
+
+ # macosx with ARCHFLAGS set and empty _CONFIG_VARS
+ os.environ['ARCHFLAGS'] = '-arch i386'
+ sysconfig._CONFIG_VARS = None
+
+ # this will attempt to recreate the _CONFIG_VARS based on environment
+ # variables; used to check a problem with the PyPy's _init_posix
+ # implementation; see: issue 705
+ get_config_vars()
# linux debian sarge
os.name = 'posix'
From commits-noreply at bitbucket.org Sun May 1 20:11:22 2011
From: commits-noreply at bitbucket.org (berdario)
Date: Sun, 1 May 2011 20:11:22 +0200 (CEST)
Subject: [pypy-svn] pypy default: merge heads
Message-ID: <20110501181122.1251A2A202C@codespeak.net>
Author: Dario Bertini
Branch:
Changeset: r43833:15b9db6dfd50
Date: 2011-05-01 20:10 +0200
http://bitbucket.org/pypy/pypy/changeset/15b9db6dfd50/
Log: merge heads
diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -171,7 +171,7 @@
using only the tools provided by the Microsoft .NET SDK, since
``ilasm`` crashes when trying to assemble the pypy-cli code due to its
size. Microsoft .NET SDK 2.0.50727.42 is affected by this bug; other
-version could be affected as well: if you find a version of the SDK
+versions could be affected as well: if you find a version of the SDK
that works, please tell us.
Windows users that want to compile their own pypy-cli can install
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -31,6 +31,7 @@
necessary
* update pypy/doc/contributor.txt (and possibly LICENSE)
* update README
+* change the tracker to have a new release tag to file bugs against
* go to pypy/tool/release and run:
force-builds.py /release/
* wait for builds to complete, make sure there are no failures
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -131,25 +131,6 @@
assert self.space.eq_w(space.call_function(get, w("33")), w(None))
assert self.space.eq_w(space.call_function(get, w("33"), w(44)), w(44))
- def test_initialize_from_strdict_shared(self):
- space = self.space
- w = space.wrap
- d = {"a": w(1), "b": w(2)}
- w_d = space.newdict(from_strdict_shared=d)
- assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
- assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
-
- def test_initialize_from_strdict_really_shared(self):
- space = self.space
- w = space.wrap
- d = {"a": w(1), "b": w(2)}
- w_d = space.newdict(from_strdict_shared=d)
- assert self.space.eq_w(space.getitem(w_d, w("a")), w(1))
- assert self.space.eq_w(space.getitem(w_d, w("b")), w(2))
- d["c"] = w(41)
- assert self.space.eq_w(space.getitem(w_d, w("c")), w(41))
-
-
class AppTest_DictObject:
def setup_class(cls):
diff --git a/pypy/translator/cli/src/ll_math.cs b/pypy/translator/cli/src/ll_math.cs
--- a/pypy/translator/cli/src/ll_math.cs
+++ b/pypy/translator/cli/src/ll_math.cs
@@ -25,13 +25,13 @@
return result;
}
- // the following code is borrowed from
+ // the following code is borrowed from
// http://web.telia.com/~u31115556/under_construction/Functions.Cephes.CFunctions.cs
const double MAXNUM = double.MaxValue; // 1.79769313486232e308
const int MEXP = 0x7ff;
[StructLayout(LayoutKind.Explicit)] //, CLSCompliantAttribute(false)]
- struct DoubleUshorts
+ struct DoubleUshorts
{
[FieldOffset(0)] public double d;
[FieldOffset(0)] public ushort u0;
@@ -235,6 +235,11 @@
return double.IsInfinity(x);
}
+ static public bool ll_math_isfinite(double x)
+ {
+ return !double.IsNaN(x) && !double.IsInfinity(x);
+ }
+
static public double ll_math_copysign(double x, double y)
{
if (x < 0.0)
diff --git a/pypy/rlib/rsre/rsre_core.py b/pypy/rlib/rsre/rsre_core.py
--- a/pypy/rlib/rsre/rsre_core.py
+++ b/pypy/rlib/rsre/rsre_core.py
@@ -227,11 +227,12 @@
subresult = None
def move_to_next_result(self, ctx):
+ # returns either 'self' or None
result = self.subresult
if result is None:
return
if result.move_to_next_result(ctx):
- return result
+ return self
return self.find_next_result(ctx)
def find_next_result(self, ctx):
@@ -808,7 +809,7 @@
def fre(ctx, ptr, end, ppos):
return end
elif checkerfn == match_IN:
- install_jitdriver_spec('MatchIn',
+ install_jitdriver_spec('MatchIn',
greens=['ppos', 'ctx.pattern'],
reds=['ptr', 'end', 'ctx'],
debugprint=(1, 0))
@@ -822,7 +823,7 @@
else:
return ptr
elif checkerfn == match_IN_IGNORE:
- install_jitdriver_spec('MatchInIgnore',
+ install_jitdriver_spec('MatchInIgnore',
greens=['ppos', 'ctx.pattern'],
reds=['ptr', 'end', 'ctx'],
debugprint=(1, 0))
diff --git a/pypy/rlib/rsre/test/test_match.py b/pypy/rlib/rsre/test/test_match.py
--- a/pypy/rlib/rsre/test/test_match.py
+++ b/pypy/rlib/rsre/test/test_match.py
@@ -283,3 +283,7 @@
def test_match_bug2(self):
r = get_code(r'(x??)??$')
assert rsre_core.match(r, "x")
+
+ def test_match_bug3(self):
+ r = get_code(r'([ax]*?x*)?$')
+ assert rsre_core.match(r, "aaxaa")
diff --git a/pypy/config/test/test_pypyoption.py b/pypy/config/test/test_pypyoption.py
--- a/pypy/config/test/test_pypyoption.py
+++ b/pypy/config/test/test_pypyoption.py
@@ -70,6 +70,6 @@
prefix = descr._name
c = Config(descr)
for path in c.getpaths(include_groups=True):
- fn = prefix + "." + path + ".rst"
+ fn = prefix + "." + path + ".txt"
yield check_file_exists, fn
diff --git a/pypy/translator/jvm/src/pypy/PyPy.java b/pypy/translator/jvm/src/pypy/PyPy.java
--- a/pypy/translator/jvm/src/pypy/PyPy.java
+++ b/pypy/translator/jvm/src/pypy/PyPy.java
@@ -1198,6 +1198,10 @@
return Double.isInfinite(x);
}
+ public boolean ll_math_isfinite(double x) {
+ return !Double.isNaN(x) && !Double.isInfinite(x);
+ }
+
private double check(double v) {
if (Double.isNaN(v))
interlink.throwValueError();
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -37,13 +37,16 @@
#return space.call(space.type(w_self),W_SetIterObject(rdict_w))
objtype = type(w_self)
if objtype is W_SetObject:
- obj = W_SetObject(space, rdict_w)
+ w_obj = W_SetObject(space, rdict_w)
elif objtype is W_FrozensetObject:
- obj = W_FrozensetObject(space, rdict_w)
+ w_obj = W_FrozensetObject(space, rdict_w)
else:
- itemiterator = space.iter(W_SetIterObject(rdict_w))
- obj = space.call_function(space.type(w_self),itemiterator)
- return obj
+ w_type = space.type(w_self)
+ _, w_newdescr = w_type.lookup_where('__new__')
+ w_newfunc = space.get(w_newdescr, w_type)
+ w_itemiterator = W_SetIterObject(rdict_w)
+ w_obj = space.call_function(w_newfunc, w_type, w_itemiterator)
+ return w_obj
_lifeline_ = None
def getweakref(self):
From commits-noreply at bitbucket.org Sun May 1 21:12:55 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Sun, 1 May 2011 21:12:55 +0200 (CEST)
Subject: [pypy-svn] pypy default: Move pre/post -amble of hash__Tuple into a
seperate function so allocations can be removed.
Message-ID: <20110501191255.97A7E282B59@codespeak.net>
Author: Alex Gaynor
Branch:
Changeset: r43834:c1bb87039d0d
Date: 2011-05-01 15:09 -0400
http://bitbucket.org/pypy/pypy/changeset/c1bb87039d0d/
Log: Move pre/post -amble of hash__Tuple into a seperate function so
allocations can be removed.
diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py
--- a/pypy/objspace/std/tupleobject.py
+++ b/pypy/objspace/std/tupleobject.py
@@ -88,7 +88,7 @@
if times == 1 and space.type(w_tuple) == space.w_tuple:
return w_tuple
items = w_tuple.wrappeditems
- return W_TupleObject(items * times)
+ return W_TupleObject(items * times)
def mul__Tuple_ANY(space, w_tuple, w_times):
return mul_tuple_times(space, w_tuple, w_times)
@@ -146,17 +146,20 @@
+ ")")
def hash__Tuple(space, w_tuple):
+ return space.wrap(hash_tuple(space, w_tuple.wrappeditems))
+
+def hash_tuple(space, wrappeditems):
# this is the CPython 2.4 algorithm (changed from 2.3)
mult = 1000003
x = 0x345678
- z = len(w_tuple.wrappeditems)
- for w_item in w_tuple.wrappeditems:
+ z = len(wrappeditems)
+ for w_item in wrappeditems:
y = space.int_w(space.hash(w_item))
x = (x ^ y) * mult
z -= 1
mult += 82520 + z + z
x += 97531
- return space.wrap(intmask(x))
+ return intmask(x)
def getnewargs__Tuple(space, w_tuple):
return space.newtuple([W_TupleObject(w_tuple.wrappeditems)])
From commits-noreply at bitbucket.org Sun May 1 21:12:59 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Sun, 1 May 2011 21:12:59 +0200 (CEST)
Subject: [pypy-svn] pypy default: Merged upstream.
Message-ID: <20110501191259.E1D1C2A202B@codespeak.net>
Author: Alex Gaynor
Branch:
Changeset: r43835:4b9a838b0bb7
Date: 2011-05-01 15:11 -0400
http://bitbucket.org/pypy/pypy/changeset/4b9a838b0bb7/
Log: Merged upstream.
diff --git a/lib-python/modified-2.7/sysconfig.py b/lib-python/modified-2.7/sysconfig.py
--- a/lib-python/modified-2.7/sysconfig.py
+++ b/lib-python/modified-2.7/sysconfig.py
@@ -369,10 +369,11 @@
# patched up as well.
'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'):
- flags = _CONFIG_VARS[key]
- flags = re.sub('-arch\s+\w+\s', ' ', flags)
- flags = flags + ' ' + arch
- _CONFIG_VARS[key] = flags
+ if key in _CONFIG_VARS:
+ flags = _CONFIG_VARS[key]
+ flags = re.sub('-arch\s+\w+\s', ' ', flags)
+ flags = flags + ' ' + arch
+ _CONFIG_VARS[key] = flags
# If we're on OSX 10.5 or later and the user tries to
# compiles an extension using an SDK that is not present
diff --git a/lib-python/modified-2.7/test/test_sysconfig.py b/lib-python/modified-2.7/test/test_sysconfig.py
--- a/lib-python/modified-2.7/test/test_sysconfig.py
+++ b/lib-python/modified-2.7/test/test_sysconfig.py
@@ -210,13 +210,22 @@
self.assertEqual(get_platform(), 'macosx-10.4-fat64')
- for arch in ('ppc', 'i386', 'x86_64', 'ppc64'):
+ for arch in ('ppc', 'i386', 'ppc64', 'x86_64'):
get_config_vars()['CFLAGS'] = ('-arch %s -isysroot '
'/Developer/SDKs/MacOSX10.4u.sdk '
'-fno-strict-aliasing -fno-common '
'-dynamic -DNDEBUG -g -O3'%(arch,))
self.assertEqual(get_platform(), 'macosx-10.4-%s'%(arch,))
+
+ # macosx with ARCHFLAGS set and empty _CONFIG_VARS
+ os.environ['ARCHFLAGS'] = '-arch i386'
+ sysconfig._CONFIG_VARS = None
+
+ # this will attempt to recreate the _CONFIG_VARS based on environment
+ # variables; used to check a problem with the PyPy's _init_posix
+ # implementation; see: issue 705
+ get_config_vars()
# linux debian sarge
os.name = 'posix'
From commits-noreply at bitbucket.org Mon May 2 21:47:08 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 21:47:08 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Add comments.
Message-ID: <20110502194708.05D1936C209@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43837:641965a1b6cf
Date: 2011-05-02 11:32 +0200
http://bitbucket.org/pypy/pypy/changeset/641965a1b6cf/
Log: Add comments.
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -136,6 +136,12 @@
oldlooptoken so that from now own they will call newlooptoken."""
raise NotImplementedError
+ def invalidate_loop(self, looptoken):
+ """Activate all GUARD_NOT_INVALIDATED in the loop and its attached
+ bridges. Before this call, all GUARD_NOT_INVALIDATED do nothing;
+ after this call, they all fail."""
+ raise NotImplementedError
+
def free_loop_and_bridges(self, compiled_loop_token):
"""This method is called to free resources (machine code,
references to resume guards, etc.) allocated by the compilation
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
@@ -417,7 +417,7 @@
def optimize_GUARD_NOT_INVALIDATED(self, op):
if self._remove_guard_not_invalidated:
return
- self._remove_guard_not_invalidated = False
+ self._remove_guard_not_invalidated = False # XXX ???
if self._seen_guard_not_invalidated:
return
self._seen_guard_not_invalidated = True
From commits-noreply at bitbucket.org Mon May 2 21:47:10 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 21:47:10 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Write a test that fails if we
remove 'jit_force_quasi_immutable'
Message-ID: <20110502194710.398C236C209@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43838:13cf67c35078
Date: 2011-05-02 11:47 +0200
http://bitbucket.org/pypy/pypy/changeset/13cf67c35078/
Log: Write a test that fails if we remove 'jit_force_quasi_immutable'
from the VirtualizableAnalyzer class.
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
@@ -265,5 +265,32 @@
self.check_loop_count(7)
assert res == main()
+ def test_change_during_running(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ @dont_look_inside
+ def residual_call(foo, x):
+ if x == 5:
+ foo.a += 1
+ def f(a, x):
+ foo = Foo(a)
+ 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.a
+ residual_call(foo, x)
+ total += foo.a
+ 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)
+
class TestLLtypeGreenFieldsTests(QuasiImmutTests, LLJitMixin):
pass
From commits-noreply at bitbucket.org Mon May 2 21:47:12 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 21:47:12 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Make the effectinfo more
precise, by splitting the meaning "can
Message-ID: <20110502194712.DCCB0282B8E@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43839:0ce5319f0b96
Date: 2011-05-02 11:53 +0200
http://bitbucket.org/pypy/pypy/changeset/0ce5319f0b96/
Log: Make the effectinfo more precise, by splitting the meaning "can
force virtualizable" and "can cause guard_not_invalidated to fail".
diff --git a/pypy/jit/codewriter/call.py b/pypy/jit/codewriter/call.py
--- a/pypy/jit/codewriter/call.py
+++ b/pypy/jit/codewriter/call.py
@@ -6,6 +6,7 @@
from pypy.jit.codewriter import support
from pypy.jit.codewriter.jitcode import JitCode
from pypy.jit.codewriter.effectinfo import VirtualizableAnalyzer
+from pypy.jit.codewriter.effectinfo import QuasiImmutAnalyzer
from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze
from pypy.jit.codewriter.effectinfo import EffectInfo, CallInfoCollection
from pypy.translator.simplify import get_funcobj, get_functype
@@ -30,6 +31,7 @@
self.raise_analyzer = RaiseAnalyzer(translator)
self.readwrite_analyzer = ReadWriteAnalyzer(translator)
self.virtualizable_analyzer = VirtualizableAnalyzer(translator)
+ self.quasiimmut_analyzer = QuasiImmutAnalyzer(translator)
#
for index, jd in enumerate(jitdrivers_sd):
jd.index = index
@@ -220,6 +222,8 @@
if extraeffect is None:
if self.virtualizable_analyzer.analyze(op):
extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+ elif self.quasiimmut_analyzer.analyze(op):
+ extraeffect = EffectInfo.EF_CAN_INVALIDATE
elif loopinvariant:
extraeffect = EffectInfo.EF_LOOPINVARIANT
elif pure:
@@ -237,6 +241,7 @@
if pure or loopinvariant:
assert effectinfo is not None
assert extraeffect != EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+ assert extraeffect != EffectInfo.EF_CAN_INVALIDATE
#
return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
effectinfo)
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
@@ -290,7 +290,8 @@
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,
+ call_may_force=0, guard_not_forced=0)
class TestLLtypeGreenFieldsTests(QuasiImmutTests, LLJitMixin):
pass
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -13,7 +13,8 @@
EF_LOOPINVARIANT = 1 #special: call it only once per loop
EF_CANNOT_RAISE = 2 #a function which cannot raise
EF_CAN_RAISE = 3 #normal function (can raise)
- EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE = 4 #can raise and force virtualizables
+ EF_CAN_INVALIDATE = 4 #can force all GUARD_NOT_INVALIDATED
+ EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE = 5 #can raise and force virtualizables
# the 'oopspecindex' field is one of the following values:
OS_NONE = 0 # normal case, no oopspec
@@ -98,6 +99,9 @@
cls._cache[key] = result
return result
+ def check_can_invalidate(self):
+ return self.extraeffect >= self.EF_CAN_INVALIDATE
+
def check_forces_virtual_or_virtualizable(self):
return self.extraeffect >= self.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
@@ -171,8 +175,11 @@
class VirtualizableAnalyzer(BoolGraphAnalyzer):
def analyze_simple_operation(self, op, graphinfo):
return op.opname in ('jit_force_virtualizable',
- 'jit_force_virtual',
- 'jit_force_quasi_immutable')
+ 'jit_force_virtual')
+
+class QuasiImmutAnalyzer(BoolGraphAnalyzer):
+ def analyze_simple_operation(self, op, graphinfo):
+ return op.opname == 'jit_force_quasi_immutable'
# ____________________________________________________________
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
@@ -240,8 +240,7 @@
effectinfo = None
else:
effectinfo = op.getdescr().get_extra_info()
- if (effectinfo is None or effectinfo.extraeffect >=
- effectinfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE):
+ if effectinfo is None or effectinfo.check_can_invalidate():
self._seen_guard_not_invalidated = False
if effectinfo is not None:
# XXX we can get the wrong complexity here, if the lists
From commits-noreply at bitbucket.org Mon May 2 21:47:20 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Mon, 2 May 2011 21:47:20 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: update the template after alex added
the google analyitics widget
Message-ID: <20110502194720.204DA36C209@codespeak.net>
Author: Antonio Cuni
Branch: extradoc
Changeset: r3550:fbfd8832e119
Date: 2011-05-02 13:39 +0200
http://bitbucket.org/pypy/extradoc/changeset/fbfd8832e119/
Log: update the template after alex added the google analyitics widget
diff --git a/blog/template.xml b/blog/template.xml
--- a/blog/template.xml
+++ b/blog/template.xml
@@ -1,12 +1,11 @@
+
-
-
-
@@ -1543,7 +1542,7 @@
}, 10);
-
@@ -1765,4 +1764,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
From commits-noreply at bitbucket.org Mon May 2 21:47:21 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Mon, 2 May 2011 21:47:21 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: add a hack to make sure that flattr
buttons actually load
Message-ID: <20110502194721.61E54282B90@codespeak.net>
Author: Antonio Cuni
Branch: extradoc
Changeset: r3551:039dcfc45f84
Date: 2011-05-02 13:43 +0200
http://bitbucket.org/pypy/extradoc/changeset/039dcfc45f84/
Log: add a hack to make sure that flattr buttons actually load
diff --git a/blog/template.xml b/blog/template.xml
--- a/blog/template.xml
+++ b/blog/template.xml
@@ -1543,7 +1543,14 @@
From commits-noreply at bitbucket.org Mon May 2 22:41:07 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 22:41:07 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: - Improve a bit the tests.
Message-ID: <20110502204107.B6D33282B8B@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43849:75c9ec8ace14
Date: 2011-05-02 15:59 +0200
http://bitbucket.org/pypy/pypy/changeset/75c9ec8ace14/
Log: - Improve a bit the tests.
- Kill old tests.
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -5724,11 +5724,13 @@
quasiimmut_field(p0, descr=quasiimmutdescr)
guard_not_invalidated() []
i1 = getfield_gc(p0, descr=quasifielddescr)
+ escape(i1)
jump(p1, p0, i1)
"""
expected = """
[p0, p1, i0]
i1 = getfield_gc(p0, descr=quasifielddescr)
+ escape(i1)
jump(p1, p0, i1)
"""
self.optimize_loop(ops, expected)
@@ -5739,11 +5741,13 @@
quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
guard_not_invalidated() []
i1 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+ escape(i1)
jump()
"""
expected = """
[]
guard_not_invalidated() []
+ escape(-4247)
jump()
"""
self.optimize_loop(ops, expected, expected)
@@ -5778,32 +5782,3 @@
jump(i0)
"""
self.optimize_loop(ops, expected)
-
-##class TestOOtype(OptimizeOptTest, OOtypeMixin):
-
-## def test_instanceof(self):
-## ops = """
-## [i0]
-## p0 = new_with_vtable(ConstClass(node_vtable))
-## i1 = instanceof(p0, descr=nodesize)
-## jump(i1)
-## """
-## expected = """
-## [i0]
-## jump(1)
-## """
-## self.optimize_loop(ops, expected)
-
-## def test_instanceof_guard_class(self):
-## ops = """
-## [i0, p0]
-## guard_class(p0, ConstClass(node_vtable)) []
-## i1 = instanceof(p0, descr=nodesize)
-## jump(i1, p0)
-## """
-## expected = """
-## [i0, p0]
-## guard_class(p0, ConstClass(node_vtable)) []
-## jump(1, p0)
-## """
-## self.optimize_loop(ops, expected)
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
@@ -70,6 +70,7 @@
('mutate_field', rclass.OBJECTPTR),
hints={'immutable_fields': accessor})
quasi = lltype.malloc(QUASI, immortal=True)
+ quasi.inst_field = -4247
quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field')
quasibox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, quasi))
quasiimmutdescr = QuasiImmutDescr(cpu, quasibox,
From commits-noreply at bitbucket.org Mon May 2 22:41:10 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 22:41:10 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Write a direct backend test
for GUARD_NOT_INVALIDATED.
Message-ID: <20110502204110.90296282B92@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43850:6dc09df6c1a2
Date: 2011-05-02 16:18 +0200
http://bitbucket.org/pypy/pypy/changeset/6dc09df6c1a2/
Log: Write a direct backend test for GUARD_NOT_INVALIDATED.
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -5754,15 +5754,19 @@
def test_remove_extra_guards_not_invalidated(self):
ops = """
- []
+ [i0]
guard_not_invalidated() []
guard_not_invalidated() []
- jump()
- """
- expected = """
- []
+ i1 = int_add(i0, 1)
guard_not_invalidated() []
- jump()
+ guard_not_invalidated() []
+ jump(i1)
+ """
+ expected = """
+ [i0]
+ guard_not_invalidated() []
+ i1 = int_add(i0, 1)
+ jump(i1)
"""
self.optimize_loop(ops, expected)
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
@@ -22,7 +22,6 @@
"""Returns the current QuasiImmut instance in the field,
possibly creating one.
"""
- # XXX this is broken on x86
qmut_gcref = cpu.bh_getfield_gc_r(gcref, mutatefielddescr)
if qmut_gcref:
qmut = QuasiImmut.show(cpu, qmut_gcref)
@@ -78,7 +77,8 @@
def invalidate(self):
# When this is called, all the loops that we record become
- # invalid and must not be called again, nor returned to.
+ # invalid: all GUARD_NOT_INVALIDATED in these loops (and
+ # in attached bridges) must now fail.
wrefs = self.looptokens_wrefs
self.looptokens_wrefs = []
for wref in wrefs:
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -139,7 +139,11 @@
def invalidate_loop(self, looptoken):
"""Activate all GUARD_NOT_INVALIDATED in the loop and its attached
bridges. Before this call, all GUARD_NOT_INVALIDATED do nothing;
- after this call, they all fail."""
+ after this call, they all fail. Note that afterwards, if one such
+ guard fails often enough, it has a bridge attached to it; it is
+ possible then to re-call invalidate_loop() on the same looptoken,
+ which must invalidate all newer GUARD_NOT_INVALIDATED, but not the
+ old one that already has a bridge attached to it."""
raise NotImplementedError
def free_loop_and_bridges(self, compiled_loop_token):
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -1817,6 +1817,58 @@
assert self.cpu.get_latest_value_int(2) == 10
assert values == [1, 10]
+ def test_guard_not_invalidated(self):
+ cpu = self.cpu
+ i0 = BoxInt()
+ i1 = BoxInt()
+ faildescr = BasicFailDescr(1)
+ ops = [
+ ResOperation(rop.GUARD_NOT_INVALIDATED, [], None, descr=faildescr),
+ ResOperation(rop.FINISH, [i0], None, descr=BasicFailDescr(0))
+ ]
+ ops[0].setfailargs([i1])
+ looptoken = LoopToken()
+ self.cpu.compile_loop([i0, i1], ops, looptoken)
+
+ self.cpu.set_future_value_int(0, -42)
+ self.cpu.set_future_value_int(1, 9)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail.identifier == 0
+ assert self.cpu.get_latest_value_int(0) == -42
+
+ # mark as failing
+ self.cpu.invalidate_loop(looptoken)
+
+ self.cpu.set_future_value_int(0, -42)
+ self.cpu.set_future_value_int(1, 9)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail is faildescr
+ assert self.cpu.get_latest_value_int(0) == 9
+
+ # attach a bridge
+ i2 = BoxInt()
+ faildescr2 = BasicFailDescr(2)
+ ops = [
+ ResOperation(rop.GUARD_NOT_INVALIDATED, [],None, descr=faildescr2),
+ ResOperation(rop.FINISH, [i2], None, descr=BasicFailDescr(3))
+ ]
+ ops[0].setfailargs([])
+ self.cpu.compile_bridge(faildescr, [i2], ops, looptoken)
+
+ self.cpu.set_future_value_int(0, -42)
+ self.cpu.set_future_value_int(1, 9)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail.identifier == 3
+ assert self.cpu.get_latest_value_int(0) == 9
+
+ # mark as failing again
+ self.cpu.invalidate_loop(looptoken)
+
+ self.cpu.set_future_value_int(0, -42)
+ self.cpu.set_future_value_int(1, 9)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail is faildescr2
+
# pure do_ / descr features
def test_do_operations(self):
From commits-noreply at bitbucket.org Mon May 2 22:41:12 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 22:41:12 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: The test fails on x86-64.
Fix. (How did it ever works, etc.)
Message-ID: <20110502204112.4C71A282B94@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43851:ba2beeb0c671
Date: 2011-05-02 16:39 +0200
http://bitbucket.org/pypy/pypy/changeset/ba2beeb0c671/
Log: The test fails on x86-64. Fix. (How did it ever works, etc.)
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -502,7 +502,7 @@
if WORD == 4:
adr_target += 5 # CALL imm
else:
- adr_target += 13 # MOV r11, imm; CALL *r11
+ adr_target += 13 # MOV r11, imm-as-8-bytes; CALL *r11 xxxxxxxxxx
return adr_target
def patch_jump_for_descr(self, faildescr, adr_new_target):
@@ -518,9 +518,9 @@
mc.writeimm32(offset)
mc.copy_to_raw_memory(adr_jump_offset)
else:
- # "mov r11, addr; jmp r11" is 13 bytes, which fits in there
- # because we always write "mov r11, addr; call *r11" in the
- # first place.
+ # "mov r11, addr; jmp r11" is up to 13 bytes, which fits in there
+ # because we always write "mov r11, imm-as-8-bytes; call *r11" in
+ # the first place.
mc.MOV_ri(X86_64_SCRATCH_REG.value, adr_new_target)
mc.JMP_r(X86_64_SCRATCH_REG.value)
p = rffi.cast(rffi.INTP, adr_jump_offset)
@@ -1596,7 +1596,18 @@
withfloats = True
break
exc = guardtok.exc
- mc.CALL(imm(self.failure_recovery_code[exc + 2 * withfloats]))
+ target = self.failure_recovery_code[exc + 2 * withfloats]
+ if WORD == 4:
+ mc.CALL(imm(target))
+ else:
+ # Generate exactly 13 bytes:
+ # MOV r11, target-as-8-bytes
+ # CALL *r11
+ # Keep the number 13 in sync with _find_failure_recovery_bytecode.
+ start = mc.get_relative_pos()
+ mc.MOV_ri64(X86_64_SCRATCH_REG.value, target)
+ mc.CALL_r(X86_64_SCRATCH_REG.value)
+ assert mc.get_relative_pos() == start + 13
# write tight data that describes the failure recovery
self.write_failure_recovery_description(mc, guardtok.failargs,
guardtok.fail_locs)
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -1835,6 +1835,8 @@
fail = self.cpu.execute_token(looptoken)
assert fail.identifier == 0
assert self.cpu.get_latest_value_int(0) == -42
+ print 'step 1 ok'
+ print '-'*79
# mark as failing
self.cpu.invalidate_loop(looptoken)
@@ -1844,6 +1846,8 @@
fail = self.cpu.execute_token(looptoken)
assert fail is faildescr
assert self.cpu.get_latest_value_int(0) == 9
+ print 'step 2 ok'
+ print '-'*79
# attach a bridge
i2 = BoxInt()
@@ -1860,6 +1864,8 @@
fail = self.cpu.execute_token(looptoken)
assert fail.identifier == 3
assert self.cpu.get_latest_value_int(0) == 9
+ print 'step 3 ok'
+ print '-'*79
# mark as failing again
self.cpu.invalidate_loop(looptoken)
@@ -1868,6 +1874,8 @@
self.cpu.set_future_value_int(1, 9)
fail = self.cpu.execute_token(looptoken)
assert fail is faildescr2
+ print 'step 4 ok'
+ print '-'*79
# pure do_ / descr features
From commits-noreply at bitbucket.org Mon May 2 22:41:15 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 22:41:15 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Add a comment describing the
implicit assumptions made by this logic.
Message-ID: <20110502204115.11EA5282B9D@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43852:df19615b3755
Date: 2011-05-02 16:47 +0200
http://bitbucket.org/pypy/pypy/changeset/df19615b3755/
Log: Add a comment describing the implicit assumptions made by this
logic.
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -456,6 +456,17 @@
relpos = tok.pos_jump_offset
clt.invalidate_positions.append((rawstart + relpos,
relative_target))
+ # General idea: Although no code was generated by this
+ # guard, the code might be patched with a "JMP rel32" to
+ # the guard recovery code. This recovery code is
+ # already generated, and looks like the recovery code
+ # for any guard, even if at first it has no jump to it.
+ # So we may later write 5 bytes overriding the existing
+ # instructions; this works because a CALL instruction
+ # would also take at least 5 bytes. If it could take
+ # less, we would run into the issue that overwriting the
+ # 5 bytes here might get a few nonsense bytes at the
+ # return address of the following CALL.
def get_asmmemmgr_blocks(self, looptoken):
clt = looptoken.compiled_loop_token
From commits-noreply at bitbucket.org Mon May 2 22:41:17 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 22:41:17 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: An extra passing test.
Message-ID: <20110502204117.2D989282B9D@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43853:11566ad5e0d7
Date: 2011-05-02 17:30 +0200
http://bitbucket.org/pypy/pypy/changeset/11566ad5e0d7/
Log: An extra passing test.
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -5786,3 +5786,28 @@
jump(i0)
"""
self.optimize_loop(ops, expected)
+
+ def test_call_may_force_invalidated_guards_reload(self):
+ ops = """
+ [i0a, i0b]
+ quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i1 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+ call_may_force(i0b, descr=mayforcevirtdescr)
+ quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i2 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+ i3 = escape(i1)
+ i4 = escape(i2)
+ jump(i3, i4)
+ """
+ expected = """
+ [i0a, i0b]
+ guard_not_invalidated() []
+ call_may_force(i0b, descr=mayforcevirtdescr)
+ guard_not_invalidated() []
+ i3 = escape(-4247)
+ i4 = escape(-4247)
+ jump(i3, i4)
+ """
+ self.optimize_loop(ops, expected)
From commits-noreply at bitbucket.org Mon May 2 22:41:21 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Mon, 2 May 2011 22:41:21 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Remove the restriction that
a setfield(quasiimmut) should not be
Message-ID: <20110502204121.A4741282B96@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43854:19053f4afad7
Date: 2011-05-02 22:29 +0200
http://bitbucket.org/pypy/pypy/changeset/19053f4afad7/
Log: Remove the restriction that a setfield(quasiimmut) should not be
seen during tracing. Instead, it is seen, together with the
jit_force_quasi_immutable just before, which is now implemented in
the tracer and in the blackhole interp. See comment in
opimpl_jit_force_quasi_immutable().
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
@@ -45,6 +45,14 @@
#
return invalidation
+def do_force_quasi_immutable(cpu, p, mutatefielddescr):
+ qmut_ref = cpu.bh_getfield_gc_r(p, mutatefielddescr)
+ if qmut_ref:
+ cpu.bh_setfield_gc_r(p, mutatefielddescr, cpu.ts.NULLREF)
+ qmut_ptr = lltype.cast_opaque_ptr(rclass.OBJECTPTR, qmut_ref)
+ qmut = cast_base_ptr_to_instance(QuasiImmut, qmut_ptr)
+ qmut.invalidate()
+
class QuasiImmut(object):
llopaque = True
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
@@ -69,6 +69,7 @@
QUASI = lltype.GcStruct('QUASIIMMUT', ('inst_field', lltype.Signed),
('mutate_field', rclass.OBJECTPTR),
hints={'immutable_fields': accessor})
+ quasisize = cpu.sizeof(QUASI)
quasi = lltype.malloc(QUASI, immortal=True)
quasi.inst_field = -4247
quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field')
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
@@ -15,7 +15,7 @@
from pypy.jit.metainterp.jitprof import EmptyProfiler
from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE
from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE, \
- ABORT_BAD_LOOP
+ ABORT_BAD_LOOP, ABORT_FORCE_QUASIIMMUT
from pypy.jit.metainterp.jitexc import JitException, get_llexception
from pypy.rlib.rarithmetic import intmask
from pypy.rlib.objectmodel import specialize
@@ -565,6 +565,20 @@
None, descr=descr)
self.generate_guard(rop.GUARD_NOT_INVALIDATED, resumepc=orgpc)
+ @arguments("box", "descr", "orgpc")
+ def opimpl_jit_force_quasi_immutable(self, box, mutatefielddescr, orgpc):
+ # 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.
+ mutatebox = self.execute_with_descr(rop.GETFIELD_GC,
+ mutatefielddescr, box)
+ if mutatebox.nonnull():
+ from pypy.jit.metainterp.quasiimmut import do_force_quasi_immutable
+ do_force_quasi_immutable(self.metainterp.cpu, box.getref_base(),
+ mutatefielddescr)
+ raise SwitchToBlackhole(ABORT_FORCE_QUASIIMMUT)
+ self.generate_guard(rop.GUARD_ISNULL, mutatebox, resumepc=orgpc)
+
def _nonstandard_virtualizable(self, pc, box):
# returns True if 'box' is actually not the "standard" virtualizable
# that is stored in metainterp.virtualizable_boxes[-1]
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
@@ -207,7 +207,6 @@
assert self.meta_interp(g, [], policy=StopAtXPolicy(external)) == g()
def test_invalidate_by_setfield(self):
- py.test.skip("Not implemented")
jitdriver = JitDriver(greens=['bc', 'foo'], reds=['i', 'total'])
class Foo(object):
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
@@ -410,6 +410,7 @@
# perform the replacement in the list of operations
fieldvalue = self.getvalue(qmutdescr.constantfieldbox)
cf = self.field_cache(qmutdescr.fielddescr)
+ cf.force_lazy_setfield(self)
cf.remember_field_value(structvalue, fieldvalue)
self._remove_guard_not_invalidated = False
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -1174,11 +1174,15 @@
def bhimpl_setfield_raw_f(cpu, struct, fielddescr, newvalue):
cpu.bh_setfield_raw_f(struct, fielddescr, newvalue)
- @arguments("cpu", "r", "d", "d")
- def bhimpl_record_quasiimmut_field(self, struct, fielddescr,
- mutatefielddescr):
+ @arguments("r", "d", "d")
+ def bhimpl_record_quasiimmut_field(struct, fielddescr, mutatefielddescr):
pass
+ @arguments("cpu", "r", "d")
+ def bhimpl_jit_force_quasi_immutable(cpu, struct, mutatefielddescr):
+ from pypy.jit.metainterp import quasiimmut
+ quasiimmut.do_force_quasi_immutable(cpu, struct, mutatefielddescr)
+
@arguments("cpu", "d", returns="r")
def bhimpl_new(cpu, descr):
return cpu.bh_new(descr)
diff --git a/pypy/jit/metainterp/jitprof.py b/pypy/jit/metainterp/jitprof.py
--- a/pypy/jit/metainterp/jitprof.py
+++ b/pypy/jit/metainterp/jitprof.py
@@ -22,6 +22,7 @@
ABORT_BRIDGE
ABORT_ESCAPE
ABORT_BAD_LOOP
+ABORT_FORCE_QUASIIMMUT
NVIRTUALS
NVHOLES
NVREUSED
@@ -179,6 +180,8 @@
self._print_intline("abort: compiling", cnt[ABORT_BRIDGE])
self._print_intline("abort: vable escape", cnt[ABORT_ESCAPE])
self._print_intline("abort: bad loop", cnt[ABORT_BAD_LOOP])
+ self._print_intline("abort: force quasi-immut",
+ cnt[ABORT_FORCE_QUASIIMMUT])
self._print_intline("nvirtuals", cnt[NVIRTUALS])
self._print_intline("nvholes", cnt[NVHOLES])
self._print_intline("nvreused", cnt[NVREUSED])
diff --git a/pypy/jit/codewriter/policy.py b/pypy/jit/codewriter/policy.py
--- a/pypy/jit/codewriter/policy.py
+++ b/pypy/jit/codewriter/policy.py
@@ -1,5 +1,5 @@
from pypy.translator.simplify import get_funcobj
-from pypy.jit.metainterp import history, quasiimmut
+from pypy.jit.metainterp import history
from pypy.rpython.lltypesystem import lltype, rclass
from pypy.tool.udir import udir
@@ -82,20 +82,12 @@
getkind(v.concretetype, supports_floats, supports_longlong)
v = op.result
getkind(v.concretetype, supports_floats, supports_longlong)
- check_skip_operation(op)
except NotImplementedError, e:
log.WARNING('%s, ignoring graph' % (e,))
log.WARNING(' %s' % (graph,))
return True
return False
-def check_skip_operation(op):
- if op.opname == 'setfield':
- if quasiimmut.is_quasi_immutable(op.args[0].concretetype.TO,
- op.args[1].value):
- raise NotImplementedError("write to quasi-immutable field %r"
- % (op.args[1].value,))
-
# ____________________________________________________________
class StopAtXPolicy(JitPolicy):
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -5811,3 +5811,28 @@
jump(i3, i4)
"""
self.optimize_loop(ops, expected)
+
+ def test_call_may_force_invalidated_guards_virtual(self):
+ ops = """
+ [i0a, i0b]
+ p = new(descr=quasisize)
+ setfield_gc(p, 421, descr=quasifielddescr)
+ quasiimmut_field(p, descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i1 = getfield_gc(p, descr=quasifielddescr)
+ call_may_force(i0b, descr=mayforcevirtdescr)
+ quasiimmut_field(p, descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i2 = getfield_gc(p, descr=quasifielddescr)
+ i3 = escape(i1)
+ i4 = escape(i2)
+ jump(i3, i4)
+ """
+ expected = """
+ [i0a, i0b]
+ call_may_force(i0b, descr=mayforcevirtdescr)
+ i3 = escape(421)
+ i4 = escape(421)
+ jump(i3, i4)
+ """
+ self.optimize_loop(ops, expected)
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
@@ -7,7 +7,7 @@
from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets
from pypy.jit.codewriter import support, heaptracker, longlong
from pypy.jit.codewriter.effectinfo import EffectInfo
-from pypy.jit.codewriter.policy import log, check_skip_operation
+from pypy.jit.codewriter.policy import log
from pypy.jit.metainterp.typesystem import deref, arrayItem
from pypy.jit.metainterp import quasiimmut
from pypy.rlib import objectmodel
@@ -361,7 +361,7 @@
# If the resulting op1 is still a direct_call, turn it into a
# residual_call.
if isinstance(op1, SpaceOperation) and op1.opname == 'direct_call':
- op1 = self.handle_residual_call(op1 or op)
+ op1 = self.handle_residual_call(op1)
return op1
def handle_recursive_call(self, op):
@@ -590,7 +590,6 @@
return op1
def rewrite_op_setfield(self, op):
- check_skip_operation(op) # just to check it doesn't raise
if self.is_typeptr_getset(op):
# ignore the operation completely -- instead, it's done by 'new'
return
@@ -1374,6 +1373,15 @@
self.vable_flags[op.args[0]] = op.args[2].value
return []
+ def rewrite_op_jit_force_quasi_immutable(self, op):
+ v_inst, c_fieldname = op.args
+ descr1 = self.cpu.fielddescrof(v_inst.concretetype.TO,
+ c_fieldname.value)
+ op0 = SpaceOperation('-live-', [], None)
+ op1 = SpaceOperation('jit_force_quasi_immutable', [v_inst, descr1],
+ None)
+ return [op0, op1]
+
# ____________________________________________________________
class NotSupported(Exception):
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
@@ -982,8 +982,13 @@
('mutate_x', rclass.OBJECTPTR),
hints={'immutable_fields': accessor})
for v_x in [const(lltype.malloc(STRUCT)), varoftype(lltype.Ptr(STRUCT))]:
- op = SpaceOperation('setfield',
- [v_x, Constant('inst_x', lltype.Void), v1],
+ op = SpaceOperation('jit_force_quasi_immutable',
+ [v_x, Constant('mutate_x', lltype.Void)],
varoftype(lltype.Void))
- tr = Transformer(FakeCPU())
- raises(NotImplementedError, tr.rewrite_operation, op)
+ tr = Transformer(FakeCPU(), FakeRegularCallControl())
+ tr.graph = 'currentgraph'
+ op0, op1 = tr.rewrite_operation(op)
+ assert op0.opname == '-live-'
+ assert op1.opname == 'jit_force_quasi_immutable'
+ assert op1.args[0] == v_x
+ assert op1.args[1] == ('fielddescr', STRUCT, 'mutate_x')
From commits-noreply at bitbucket.org Mon May 2 23:23:36 2011
From: commits-noreply at bitbucket.org (RonnyPfannschmidt)
Date: Mon, 2 May 2011 23:23:36 +0200 (CEST)
Subject: [pypy-svn] buildbot default: switch from diff per file to diff per
commit, gives a speed boost and directory rename implication
Message-ID: <20110502212336.4BCA9282B8B@codespeak.net>
Author: Ronny Pfannschmidt
Branch:
Changeset: r498:4390f9be94d8
Date: 2011-05-02 23:22 +0200
http://bitbucket.org/pypy/buildbot/changeset/4390f9be94d8/
Log: switch from diff per file to diff per commit, gives a speed boost
and directory rename implication
diff --git a/bitbucket_hook/scm.py b/bitbucket_hook/scm.py
--- a/bitbucket_hook/scm.py
+++ b/bitbucket_hook/scm.py
@@ -19,18 +19,25 @@
return unicode(stdout, encoding='utf-8', errors='replace')
-def get_diff(local_repo, hgid, files):
- import re
- binary = re.compile('^GIT binary patch$', re.MULTILINE)
- files = [item['file'] for item in files]
+def get_diff(local_repo, hgid):
+ out = hg('-R', local_repo, 'diff', '--git', '-c', hgid)
+ out = out.splitlines(True)
+ out_iter = iter(out)
lines = []
- for filename in files:
- out = hg('-R', local_repo, 'diff', '--git', '-c', hgid,
- local_repo.join(filename))
- match = binary.search(out)
- if match:
- # it's a binary patch, omit the content
- out = out[:match.end()]
- out += u'\n[cut]'
- lines.append(out)
- return u'\n'.join(lines)
+ for line in out_iter:
+ lines.append(line)
+ if line == 'GIT binary patch\n':
+ out_iter.next() # discard literal line
+ lines.append('\n[cut]\n')
+
+ for item in out_iter:
+ if item[0]!='z':
+ break # binary patches end with a empty line
+
+
+ return u''.join(lines)
+
+
+if __name__=='__main__':
+ # needs the pypy repo
+ print get_diff(sys.argv[1], '426be91e82b0f91b09a028993d2364f1d62f1615').encode('utf-8')
diff --git a/bitbucket_hook/mail.py b/bitbucket_hook/mail.py
--- a/bitbucket_hook/mail.py
+++ b/bitbucket_hook/mail.py
@@ -31,7 +31,7 @@
subject = '%s %s: %s' % (reponame, commit['branch'], line0)
body = scm.hg('-R', local_repo, 'log', '-r', hgid,
'--template', template)
- diff = scm.get_diff(local_repo, hgid, commit['files'])
+ diff = scm.get_diff(local_repo, hgid)
body = body + diff
send(sender, app.config['ADDRESS'], subject, body, test)
From commits-noreply at bitbucket.org Tue May 3 11:05:54 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Tue, 3 May 2011 11:05:54 +0200 (CEST)
Subject: [pypy-svn] pypy default: Port the fix in ba2beeb0c671 from
out-of-line-guards-2.
Message-ID: <20110503090554.D67BD36C206@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43855:46956b6cd3c1
Date: 2011-05-03 11:05 +0200
http://bitbucket.org/pypy/pypy/changeset/46956b6cd3c1/
Log: Port the fix in ba2beeb0c671 from out-of-line-guards-2.
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -490,7 +490,7 @@
if WORD == 4:
adr_target += 5 # CALL imm
else:
- adr_target += 13 # MOV r11, imm; CALL *r11
+ adr_target += 13 # MOV r11, imm-as-8-bytes; CALL *r11 xxxxxxxxxx
return adr_target
def patch_jump_for_descr(self, faildescr, adr_new_target):
@@ -506,9 +506,9 @@
mc.writeimm32(offset)
mc.copy_to_raw_memory(adr_jump_offset)
else:
- # "mov r11, addr; jmp r11" is 13 bytes, which fits in there
- # because we always write "mov r11, addr; call *r11" in the
- # first place.
+ # "mov r11, addr; jmp r11" is up to 13 bytes, which fits in there
+ # because we always write "mov r11, imm-as-8-bytes; call *r11" in
+ # the first place.
mc.MOV_ri(X86_64_SCRATCH_REG.value, adr_new_target)
mc.JMP_r(X86_64_SCRATCH_REG.value)
p = rffi.cast(rffi.INTP, adr_jump_offset)
@@ -1576,7 +1576,18 @@
withfloats = True
break
exc = guardtok.exc
- mc.CALL(imm(self.failure_recovery_code[exc + 2 * withfloats]))
+ target = self.failure_recovery_code[exc + 2 * withfloats]
+ if WORD == 4:
+ mc.CALL(imm(target))
+ else:
+ # Generate exactly 13 bytes:
+ # MOV r11, target-as-8-bytes
+ # CALL *r11
+ # Keep the number 13 in sync with _find_failure_recovery_bytecode.
+ start = mc.get_relative_pos()
+ mc.MOV_ri64(X86_64_SCRATCH_REG.value, target)
+ mc.CALL_r(X86_64_SCRATCH_REG.value)
+ assert mc.get_relative_pos() == start + 13
# write tight data that describes the failure recovery
self.write_failure_recovery_description(mc, guardtok.failargs,
guardtok.fail_locs)
From commits-noreply at bitbucket.org Tue May 3 13:35:14 2011
From: commits-noreply at bitbucket.org (cfbolz)
Date: Tue, 3 May 2011 13:35:14 +0200 (CEST)
Subject: [pypy-svn] pypy default: fix staticmethod.__new__
Message-ID: <20110503113514.538E5282B8E@codespeak.net>
Author: Carl Friedrich Bolz
Branch:
Changeset: r43856:2d89c6b23446
Date: 2011-05-03 13:34 +0200
http://bitbucket.org/pypy/pypy/changeset/2d89c6b23446/
Log: fix staticmethod.__new__
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -600,8 +600,10 @@
"""staticmethod(x).__get__(obj[, type]) -> x"""
return self.w_function
- def descr_staticmethod__new__(space, w_type, w_function):
- return space.wrap(StaticMethod(w_function))
+ def descr_staticmethod__new__(space, w_subtype, w_function):
+ instance = space.allocate_instance(StaticMethod, w_subtype)
+ instance.__init__(w_function)
+ return space.wrap(instance)
class ClassMethod(Wrappable):
"""The classmethod objects."""
diff --git a/pypy/module/__builtin__/test/test_descriptor.py b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -17,6 +17,12 @@
assert d.f("abc", "def") == "abcdef"
assert D.f("abc", "def") == "abcdef"
+ def test_staticmethod(self):
+ class Static(staticmethod):
+ pass
+ x = Static(1)
+ assert isinstance(x, Static)
+
def test_classmethod(self):
class C(object):
def f(cls, stuff):
From commits-noreply at bitbucket.org Tue May 3 13:39:53 2011
From: commits-noreply at bitbucket.org (cfbolz)
Date: Tue, 3 May 2011 13:39:53 +0200 (CEST)
Subject: [pypy-svn] pypy default: add a test for classmethods too,
fix name clash
Message-ID: <20110503113953.9F010282B8E@codespeak.net>
Author: Carl Friedrich Bolz
Branch:
Changeset: r43857:d999d50f2f77
Date: 2011-05-03 13:39 +0200
http://bitbucket.org/pypy/pypy/changeset/d999d50f2f77/
Log: add a test for classmethods too, fix name clash
diff --git a/pypy/module/__builtin__/test/test_descriptor.py b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -17,7 +17,7 @@
assert d.f("abc", "def") == "abcdef"
assert D.f("abc", "def") == "abcdef"
- def test_staticmethod(self):
+ def test_staticmethod_subclass(self):
class Static(staticmethod):
pass
x = Static(1)
@@ -38,6 +38,12 @@
assert d.f("abc") == (D, "abc")
assert D.f("abc") == (D, "abc")
+ def test_classmethod_subclass(self):
+ class Classm(classmethod):
+ pass
+ x = Classm(1)
+ assert isinstance(x, Classm)
+
def test_property_simple(self):
class a(object):
From commits-noreply at bitbucket.org Tue May 3 16:10:07 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Tue, 3 May 2011 16:10:07 +0200 (CEST)
Subject: [pypy-svn] pypy default: Write a test that fails on x86 on the
operation FINISH(ConstFloat(x)).
Message-ID: <20110503141007.85BB836C205@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43858:bc71e715e308
Date: 2011-05-03 16:09 +0200
http://bitbucket.org/pypy/pypy/changeset/bc71e715e308/
Log: Write a test that fails on x86 on the operation
FINISH(ConstFloat(x)).
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -316,6 +316,30 @@
fail = self.cpu.execute_token(looptoken)
assert fail is faildescr
+ if self.cpu.supports_floats:
+ looptoken = LoopToken()
+ f0 = BoxFloat()
+ operations = [
+ ResOperation(rop.FINISH, [f0], None, descr=faildescr)
+ ]
+ self.cpu.compile_loop([f0], operations, looptoken)
+ value = longlong.getfloatstorage(-61.25)
+ self.cpu.set_future_value_float(0, value)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail is faildescr
+ res = self.cpu.get_latest_value_float(0)
+ assert longlong.getrealfloat(res) == -61.25
+
+ looptoken = LoopToken()
+ operations = [
+ ResOperation(rop.FINISH, [constfloat(42.5)], None, descr=faildescr)
+ ]
+ self.cpu.compile_loop([], operations, looptoken)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail is faildescr
+ res = self.cpu.get_latest_value_float(0)
+ assert longlong.getrealfloat(res) == 42.5
+
def test_execute_operations_in_env(self):
cpu = self.cpu
x = BoxInt(123)
From commits-noreply at bitbucket.org Tue May 3 16:12:07 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Tue, 3 May 2011 16:12:07 +0200 (CEST)
Subject: [pypy-svn] pypy default: some thoughts about a jit-aware profiler
Message-ID: <20110503141207.1D0F9282B8B@codespeak.net>
Author: Antonio Cuni
Branch:
Changeset: r43859:8eed157756c4
Date: 2011-05-03 16:11 +0200
http://bitbucket.org/pypy/pypy/changeset/8eed157756c4/
Log: some thoughts about a jit-aware profiler
diff --git a/pypy/doc/discussion/jit-profiler.rst b/pypy/doc/discussion/jit-profiler.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/discussion/jit-profiler.rst
@@ -0,0 +1,79 @@
+A JIT-aware profiler
+====================
+
+Goal: have a profiler which is aware of the PyPy JIT and which shows which
+percentage of the time have been spent in which loops.
+
+Long term goal: integrate the data collected by the profiler with the
+jitviewer.
+
+The idea is record an event in the PYPYLOG everytime we enter and exit a loop
+or a bridge.
+
+Expected output
+----------------
+
+[100] {jit-profile-enter
+loop1 # e.g. an entry bridge
+[101] jit-profile-enter}
+...
+[200] {jit-profile-enter
+loop0 # JUMP from loop1 to loop0
+[201] jit-profile-enter}
+...
+[500] {jit-profile-exit
+loop0 # e.g. because of a failing guard
+[501] jit-profile-exit}
+
+In this example, the exiting from loop1 is implicit because we are entering
+loop0. So, we spent 200-100=100 ticks in the entry bridge, and 500-200=300
+ticks in the actual loop.
+
+What to do about "inner" bridges?
+----------------------------------
+
+"Inner bridges" are those bridges which jump back to the loop where they
+originate from. There are two possible ways of dealing with them:
+
+ 1. we ignore them: we record when we enter the loop, but not when we jump to
+ a compiled inner bridge. The exit event will be recorded only in case of
+ a non-compiled guard failure or a JUMP to another loop
+
+ 2. we record the enter/exit of each inner bridge
+
+The disadvantage of solution (2) is that there are certain loops which takes
+bridges at everty single iteration. So, in this case we would record a huge
+number of events, possibly adding a lot of overhead and thus making the
+profiled data useless.
+
+
+Detecting the enter to/exit from a loop
+----------------------------------------
+
+Ways to enter:
+
+ - just after the tracing/compilation
+
+ - from the interpreter, if the loop has already been compiled
+
+ - from another loop, via a JUMP operation
+
+ - from a hot guard failure (which we ignore, in case we choose solution
+ (1) above)
+
+ - XXX: am I missing anything?
+
+Ways to exit:
+
+ - guard failure (entering blackhole)
+
+ - guard failure (jumping to a bridge) (ignored in case of solution (1))
+
+ - jump to another loop
+
+ - XXX: am I missing anything?
+
+
+About call_assembler: I think that at the beginning, we should just ignore
+call_assembler: the time spent inside the call will be accounted to the loop
+calling it.
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1662,3 +1662,20 @@
assert log.result == 300
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id('shift', "") # optimized away
+
+ def test_division_to_rshift(self):
+ def main(b):
+ res = 0
+ a = 0
+ while a < 300:
+ assert a >= 0
+ assert 0 <= b <= 10
+ res = a/b # ID: div
+ a += 1
+ return res
+ #
+ log = self.run(main, [3], threshold=200)
+ #assert log.result == 149
+ loop, = log.loops_by_filename(self.filepath)
+ import pdb;pdb.set_trace()
+ assert loop.match_by_id('div', "") # optimized away
From commits-noreply at bitbucket.org Tue May 3 16:16:38 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Tue, 3 May 2011 16:16:38 +0200 (CEST)
Subject: [pypy-svn] pypy default: Fix for bc71e715e308.
Message-ID: <20110503141638.040CC282B8B@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43860:b82188b713e2
Date: 2011-05-03 16:16 +0200
http://bitbucket.org/pypy/pypy/changeset/b82188b713e2/
Log: Fix for bc71e715e308.
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -1843,8 +1843,9 @@
for i in range(len(locs)):
loc = locs[i]
if not isinstance(loc, RegLoc):
- if isinstance(loc, StackLoc) and loc.type == FLOAT:
- self.mc.MOVSD_xb(xmm0.value, loc.value)
+ if ((isinstance(loc, StackLoc) and loc.type == FLOAT) or
+ isinstance(loc, ConstFloatLoc)):
+ self.mc.MOVSD(xmm0, loc)
adr = self.fail_boxes_float.get_addr_for_num(i)
self.mc.MOVSD(heap(adr), xmm0)
else:
From commits-noreply at bitbucket.org Tue May 3 16:16:40 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Tue, 3 May 2011 16:16:40 +0200 (CEST)
Subject: [pypy-svn] pypy default: merge heads
Message-ID: <20110503141640.B3B38282B94@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43861:87afbf37afa2
Date: 2011-05-03 16:16 +0200
http://bitbucket.org/pypy/pypy/changeset/87afbf37afa2/
Log: merge heads
diff --git a/pypy/doc/discussion/jit-profiler.rst b/pypy/doc/discussion/jit-profiler.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/discussion/jit-profiler.rst
@@ -0,0 +1,79 @@
+A JIT-aware profiler
+====================
+
+Goal: have a profiler which is aware of the PyPy JIT and which shows which
+percentage of the time have been spent in which loops.
+
+Long term goal: integrate the data collected by the profiler with the
+jitviewer.
+
+The idea is record an event in the PYPYLOG everytime we enter and exit a loop
+or a bridge.
+
+Expected output
+----------------
+
+[100] {jit-profile-enter
+loop1 # e.g. an entry bridge
+[101] jit-profile-enter}
+...
+[200] {jit-profile-enter
+loop0 # JUMP from loop1 to loop0
+[201] jit-profile-enter}
+...
+[500] {jit-profile-exit
+loop0 # e.g. because of a failing guard
+[501] jit-profile-exit}
+
+In this example, the exiting from loop1 is implicit because we are entering
+loop0. So, we spent 200-100=100 ticks in the entry bridge, and 500-200=300
+ticks in the actual loop.
+
+What to do about "inner" bridges?
+----------------------------------
+
+"Inner bridges" are those bridges which jump back to the loop where they
+originate from. There are two possible ways of dealing with them:
+
+ 1. we ignore them: we record when we enter the loop, but not when we jump to
+ a compiled inner bridge. The exit event will be recorded only in case of
+ a non-compiled guard failure or a JUMP to another loop
+
+ 2. we record the enter/exit of each inner bridge
+
+The disadvantage of solution (2) is that there are certain loops which takes
+bridges at everty single iteration. So, in this case we would record a huge
+number of events, possibly adding a lot of overhead and thus making the
+profiled data useless.
+
+
+Detecting the enter to/exit from a loop
+----------------------------------------
+
+Ways to enter:
+
+ - just after the tracing/compilation
+
+ - from the interpreter, if the loop has already been compiled
+
+ - from another loop, via a JUMP operation
+
+ - from a hot guard failure (which we ignore, in case we choose solution
+ (1) above)
+
+ - XXX: am I missing anything?
+
+Ways to exit:
+
+ - guard failure (entering blackhole)
+
+ - guard failure (jumping to a bridge) (ignored in case of solution (1))
+
+ - jump to another loop
+
+ - XXX: am I missing anything?
+
+
+About call_assembler: I think that at the beginning, we should just ignore
+call_assembler: the time spent inside the call will be accounted to the loop
+calling it.
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1662,3 +1662,20 @@
assert log.result == 300
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id('shift', "") # optimized away
+
+ def test_division_to_rshift(self):
+ def main(b):
+ res = 0
+ a = 0
+ while a < 300:
+ assert a >= 0
+ assert 0 <= b <= 10
+ res = a/b # ID: div
+ a += 1
+ return res
+ #
+ log = self.run(main, [3], threshold=200)
+ #assert log.result == 149
+ loop, = log.loops_by_filename(self.filepath)
+ import pdb;pdb.set_trace()
+ assert loop.match_by_id('div', "") # optimized away
From commits-noreply at bitbucket.org Tue May 3 16:34:13 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Tue, 3 May 2011 16:34:13 +0200 (CEST)
Subject: [pypy-svn] pypy default: skip this test,
it was checked in by mistake
Message-ID: <20110503143413.73A35282B8B@codespeak.net>
Author: Antonio Cuni
Branch:
Changeset: r43862:08c404af7383
Date: 2011-05-03 16:32 +0200
http://bitbucket.org/pypy/pypy/changeset/08c404af7383/
Log: skip this test, it was checked in by mistake
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1664,6 +1664,7 @@
assert loop.match_by_id('shift', "") # optimized away
def test_division_to_rshift(self):
+ py.test.skip('in-progress')
def main(b):
res = 0
a = 0
From commits-noreply at bitbucket.org Tue May 3 20:43:47 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Tue, 3 May 2011 20:43:47 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Implement quasi-immutable
fields which contain immutable lists,
Message-ID: <20110503184347.876A5282B90@codespeak.net>
Author: Armin Rigo
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
From commits-noreply at bitbucket.org Tue May 3 20:43:49 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Tue, 3 May 2011 20:43:49 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Revert the introduction of
the class Defaults in function.py
Message-ID: <20110503184349.22A69282B90@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43866:b4acd9ac2ad2
Date: 2011-05-03 20:37 +0200
http://bitbucket.org/pypy/pypy/changeset/b4acd9ac2ad2/
Log: Revert the introduction of the class Defaults in function.py
(manually, so I hope I didn't forget anything). Replace it with the
single line:
_immutable_fields_ = ['defs?[*]']
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -3,7 +3,6 @@
from pypy.interpreter.pycode import cpython_code_signature
from pypy.interpreter.argument import rawshape
from pypy.interpreter.argument import ArgErr
-from pypy.interpreter.function import Defaults
from pypy.tool.sourcetools import valid_identifier
from pypy.tool.pairtype import extendabletype
@@ -251,7 +250,7 @@
for x in defaults:
defs_s.append(self.bookkeeper.immutablevalue(x))
try:
- inputcells = args.match_signature(signature, Defaults(defs_s))
+ inputcells = args.match_signature(signature, defs_s)
except ArgErr, e:
raise TypeError, "signature mismatch: %s" % e.getmsg(self.name)
return inputcells
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -239,7 +239,7 @@
### Parsing for function calls ###
- def _match_signature(self, w_firstarg, scope_w, signature, defaults=None,
+ def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=None,
blindargs=0):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
@@ -247,20 +247,20 @@
"""
if jit.we_are_jitted() and self._dont_jit:
return self._match_signature_jit_opaque(w_firstarg, scope_w,
- signature, defaults,
+ signature, defaults_w,
blindargs)
return self._really_match_signature(w_firstarg, scope_w, signature,
- defaults, blindargs)
+ defaults_w, blindargs)
@jit.dont_look_inside
def _match_signature_jit_opaque(self, w_firstarg, scope_w, signature,
- defaults, blindargs):
+ defaults_w, blindargs):
return self._really_match_signature(w_firstarg, scope_w, signature,
- defaults, blindargs)
+ defaults_w, blindargs)
@jit.unroll_safe
- def _really_match_signature(self, w_firstarg, scope_w, signature, defaults=None,
- blindargs=0):
+ def _really_match_signature(self, w_firstarg, scope_w, signature,
+ defaults_w=None, blindargs=0):
#
# args_w = list of the normal actual parameters, wrapped
# kwds_w = real dictionary {'keyword': wrapped parameter}
@@ -327,7 +327,7 @@
elif avail > co_argcount:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults, 0)
+ defaults_w, 0)
# the code assumes that keywords can potentially be large, but that
# argnames is typically not too large
@@ -357,12 +357,13 @@
num_remainingkwds -= 1
missing = 0
if input_argcount < co_argcount:
- def_first = co_argcount - (0 if defaults is None else defaults.getlen())
+ def_first = co_argcount - (0 if defaults_w is None else len(defaults_w))
for i in range(input_argcount, co_argcount):
if scope_w[i] is not None:
- pass
- elif i >= def_first:
- scope_w[i] = defaults.getitem(i - def_first)
+ continue
+ defnum = i - def_first
+ if defnum >= 0:
+ scope_w[i] = defaults_w[defnum]
else:
# error: not enough arguments. Don't signal it immediately
# because it might be related to a problem with */** or
@@ -382,20 +383,20 @@
if co_argcount == 0:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults, missing)
+ defaults_w, missing)
raise ArgErrUnknownKwds(num_remainingkwds, keywords, used_keywords)
if missing:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults, missing)
+ defaults_w, missing)
return co_argcount + has_vararg + has_kwarg
def parse_into_scope(self, w_firstarg,
- scope_w, fnname, signature, defaults=None):
+ scope_w, fnname, signature, defaults_w=None):
"""Parse args and kwargs to initialize a frame
according to the signature of code object.
Store the argumentvalues into scope_w.
@@ -403,29 +404,29 @@
"""
try:
return self._match_signature(w_firstarg,
- scope_w, signature, defaults, 0)
+ scope_w, signature, defaults_w, 0)
except ArgErr, e:
raise OperationError(self.space.w_TypeError,
self.space.wrap(e.getmsg(fnname)))
- def _parse(self, w_firstarg, signature, defaults, blindargs=0):
+ def _parse(self, w_firstarg, signature, defaults_w, blindargs=0):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
"""
scopelen = signature.scope_length()
scope_w = [None] * scopelen
- self._match_signature(w_firstarg, scope_w, signature, defaults,
+ self._match_signature(w_firstarg, scope_w, signature, defaults_w,
blindargs)
return scope_w
def parse_obj(self, w_firstarg,
- fnname, signature, defaults=None, blindargs=0):
+ fnname, signature, defaults_w=None, blindargs=0):
"""Parse args and kwargs to initialize a frame
according to the signature of code object.
"""
try:
- return self._parse(w_firstarg, signature, defaults, blindargs)
+ return self._parse(w_firstarg, signature, defaults_w, blindargs)
except ArgErr, e:
raise OperationError(self.space.w_TypeError,
self.space.wrap(e.getmsg(fnname)))
@@ -474,23 +475,23 @@
- def _match_signature(self, w_firstarg, scope_w, signature, defaults=None,
+ def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=None,
blindargs=0):
self.combine_if_necessary()
# _match_signature is destructive
return Arguments._match_signature(
self, w_firstarg, scope_w, signature,
- defaults, blindargs)
+ defaults_w, blindargs)
def unpack(self):
self.combine_if_necessary()
return Arguments.unpack(self)
- def match_signature(self, signature, defaults):
+ def match_signature(self, signature, defaults_w):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
"""
- return self._parse(None, signature, defaults)
+ return self._parse(None, signature, defaults_w)
def unmatch_signature(self, signature, data_w):
"""kind of inverse of match_signature"""
@@ -603,12 +604,12 @@
class ArgErrCount(ArgErr):
def __init__(self, got_nargs, nkwds, expected_nargs, has_vararg, has_kwarg,
- defaults, missing_args):
+ defaults_w, missing_args):
self.expected_nargs = expected_nargs
self.has_vararg = has_vararg
self.has_kwarg = has_kwarg
- self.num_defaults = 0 if defaults is None else defaults.getlen()
+ self.num_defaults = 0 if defaults_w is None else len(defaults_w)
self.missing_args = missing_args
self.num_args = got_nargs
self.num_kwds = nkwds
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -21,28 +21,6 @@
assert not func.can_change_code
return func.code
-class Defaults(object):
- _immutable_fields_ = ["items[*]", "promote"]
-
- def __init__(self, items, promote=False):
- self.items = items
- self.promote = promote
-
- def getitems(self):
- # an idea - we want to promote only items that we know won't change
- # too often. this is the case for builtin functions and functions
- # with known constant defaults. Otherwise we don't want to promote
- # this so lambda a=a won't create a new trace each time it's
- # encountered
- if self.promote:
- return jit.hint(self, promote=True).items
- return self.items
-
- def getitem(self, idx):
- return self.getitems()[idx]
-
- def getlen(self):
- return len(self.getitems())
class Function(Wrappable):
"""A function is a code object captured with some environment:
@@ -50,17 +28,17 @@
and an arbitrary 'closure' passed to the code object."""
can_change_code = True
+ _immutable_fields_ = ['defs?[*]']
def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
- forcename=None, promote_defs=False):
+ forcename=None):
self.space = space
self.name = forcename or code.co_name
self.w_doc = None # lazily read from code.getdocstring()
self.code = code # Code instance
self.w_func_globals = w_globals # the globals dictionary
self.closure = closure # normally, list of Cell instances or None
- self.defs = Defaults(defs_w, promote=promote_defs)
- # wrapper around list of w_default's
+ self.defs_w = defs_w
self.w_func_dict = None # filled out below if needed
self.w_module = None
@@ -157,7 +135,7 @@
return self._flat_pycall(code, nargs, frame)
elif fast_natural_arity & Code.FLATPYCALL:
natural_arity = fast_natural_arity & 0xff
- if natural_arity > nargs >= natural_arity - self.defs.getlen():
+ if natural_arity > nargs >= natural_arity - len(self.defs_w):
assert isinstance(code, PyCode)
return self._flat_pycall_defaults(code, nargs, frame,
natural_arity - nargs)
@@ -190,12 +168,11 @@
w_arg = frame.peekvalue(nargs-1-i)
new_frame.fastlocals_w[i] = w_arg
- defs = self.defs
- ndefs = defs.getlen()
+ ndefs = len(self.defs_w)
start = ndefs - defs_to_load
i = nargs
for j in xrange(start, ndefs):
- new_frame.fastlocals_w[i] = defs.getitem(j)
+ new_frame.fastlocals_w[i] = self.defs_w[j]
i += 1
return new_frame.run()
@@ -311,7 +288,7 @@
w(self.code),
w_func_globals,
w_closure,
- nt(self.defs.getitems()),
+ nt(self.defs_w),
w_func_dict,
self.w_module,
]
@@ -346,11 +323,11 @@
if space.is_w(w_func_dict, space.w_None):
w_func_dict = None
self.w_func_dict = w_func_dict
- self.defs = Defaults(space.fixedview(w_defs))
+ self.defs_w = space.fixedview(w_defs)
self.w_module = w_module
def fget_func_defaults(self, space):
- values_w = self.defs.getitems()
+ values_w = self.defs_w
# the `None in values_w` check here is to ensure that interp-level
# functions with a default of NoneNotWrapped do not get their defaults
# exposed at applevel
@@ -360,14 +337,14 @@
def fset_func_defaults(self, space, w_defaults):
if space.is_w(w_defaults, space.w_None):
- self.defs = Defaults([])
+ self.defs_w = []
return
if not space.is_true(space.isinstance(w_defaults, space.w_tuple)):
raise OperationError( space.w_TypeError, space.wrap("func_defaults must be set to a tuple object or None") )
- self.defs = Defaults(space.fixedview(w_defaults))
+ self.defs_w = space.fixedview(w_defaults)
def fdel_func_defaults(self, space):
- self.defs = Defaults([])
+ self.defs_w = []
def fget_func_doc(self, space):
if self.w_doc is None:
@@ -629,8 +606,7 @@
def __init__(self, func):
assert isinstance(func, Function)
Function.__init__(self, func.space, func.code, func.w_func_globals,
- func.defs.getitems(), func.closure, func.name,
- promote_defs=True)
+ func.defs_w, func.closure, func.name)
self.w_doc = func.w_doc
self.w_func_dict = func.w_func_dict
self.w_module = func.w_module
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -594,7 +594,7 @@
space = func.space
activation = self.activation
scope_w = args.parse_obj(w_obj, func.name, self.sig,
- func.defs, self.minargs)
+ func.defs_w, self.minargs)
try:
w_result = activation._run(space, scope_w)
except DescrMismatch:
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -204,7 +204,7 @@
fresh_virtualizable=True)
args_matched = args.parse_into_scope(None, fresh_frame.fastlocals_w,
func.name,
- sig, func.defs)
+ sig, func.defs_w)
fresh_frame.init_cells()
return frame.run()
@@ -217,7 +217,7 @@
fresh_virtualizable=True)
args_matched = args.parse_into_scope(w_obj, fresh_frame.fastlocals_w,
func.name,
- sig, func.defs)
+ sig, func.defs_w)
fresh_frame.init_cells()
return frame.run()
diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -3,7 +3,6 @@
ArgErr, ArgErrUnknownKwds, ArgErrMultipleValues, ArgErrCount, rawshape,
Signature)
from pypy.interpreter.error import OperationError
-from pypy.interpreter.function import Defaults
class TestSignature(object):
@@ -184,7 +183,7 @@
py.test.raises(ArgErr, args._match_signature, None, l, Signature(["a"], "*"))
args = Arguments(space, [])
l = [None]
- args._match_signature(None, l, Signature(["a"]), defaults=Defaults([1]))
+ args._match_signature(None, l, Signature(["a"]), defaults_w=[1])
assert l == [1]
args = Arguments(space, [])
l = [None]
@@ -232,7 +231,7 @@
py.test.raises(ArgErr, args._match_signature, firstarg, l, Signature(["a", "b", "c", "d", "e"], "*"))
l = [None, None, None, None, None]
args = Arguments(space, arglist, w_stararg=starargs)
- args._match_signature(firstarg, l, Signature(["a", "b", "c", "d", "e"]), defaults=Defaults([1]))
+ args._match_signature(firstarg, l, Signature(["a", "b", "c", "d", "e"]), defaults_w=[1])
assert l == [4, 5, 6, 7, 1]
for j in range(len(values)):
l = [None] * (j + 1)
@@ -257,24 +256,24 @@
assert len(keywords) == len(keywords_w)
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None]
- args._match_signature(None, l, Signature(["a", "b", "c"]), defaults=Defaults([4]))
+ args._match_signature(None, l, Signature(["a", "b", "c"]), defaults_w=[4])
assert l == [1, 2, 3]
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None, None]
- args._match_signature(None, l, Signature(["a", "b", "b1", "c"]), defaults=Defaults([4, 5]))
+ args._match_signature(None, l, Signature(["a", "b", "b1", "c"]), defaults_w=[4, 5])
assert l == [1, 2, 4, 3]
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None, None]
- args._match_signature(None, l, Signature(["a", "b", "c", "d"]), defaults=Defaults([4, 5]))
+ args._match_signature(None, l, Signature(["a", "b", "c", "d"]), defaults_w=[4, 5])
assert l == [1, 2, 3, 5]
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None, None]
py.test.raises(ArgErr, args._match_signature, None, l,
- Signature(["c", "b", "a", "d"]), defaults=Defaults([4, 5]))
+ Signature(["c", "b", "a", "d"]), defaults_w=[4, 5])
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None, None]
py.test.raises(ArgErr, args._match_signature, None, l,
- Signature(["a", "b", "c1", "d"]), defaults=Defaults([4, 5]))
+ Signature(["a", "b", "c1", "d"]), defaults_w=[4, 5])
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None]
args._match_signature(None, l, Signature(["a", "b"], None, "**"))
@@ -355,10 +354,10 @@
calls = []
def _match_signature(w_firstarg, scope_w, signature,
- defaults=None, blindargs=0):
- defaults = [] if defaults is None else defaults.getitems()
+ defaults_w=None, blindargs=0):
+ defaults_w = [] if defaults_w is None else defaults_w
calls.append((w_firstarg, scope_w, signature.argnames, signature.has_vararg(),
- signature.has_kwarg(), defaults, blindargs))
+ signature.has_kwarg(), defaults_w, blindargs))
args._match_signature = _match_signature
scope_w = args.parse_obj(None, "foo", Signature(["a", "b"], None, None))
@@ -376,7 +375,7 @@
calls = []
scope_w = args.parse_obj(None, "foo", Signature(["a", "b"], "args", "kw"),
- defaults=Defaults(['x', 'y']))
+ defaults_w=['x', 'y'])
assert len(calls) == 1
assert calls[0] == (None, [None, None, None, None], ["a", "b"],
True, True,
@@ -384,7 +383,7 @@
calls = []
scope_w = args.parse_obj("obj", "foo", Signature(["a", "b"], "args", "kw"),
- defaults=Defaults(['x', 'y']), blindargs=1)
+ defaults_w=['x', 'y'], blindargs=1)
assert len(calls) == 1
assert calls[0] == ("obj", [None, None, None, None], ["a", "b"],
True, True,
@@ -413,10 +412,10 @@
calls = []
def _match_signature(w_firstarg, scope_w, signature,
- defaults=None, blindargs=0):
- defaults = [] if defaults is None else defaults.getitems()
+ defaults_w=None, blindargs=0):
+ defaults_w = [] if defaults_w is None else defaults_w
calls.append((w_firstarg, scope_w, signature.argnames, signature.has_vararg(),
- signature.has_kwarg(), defaults, blindargs))
+ signature.has_kwarg(), defaults_w, blindargs))
args._match_signature = _match_signature
scope_w = [None, None]
@@ -429,7 +428,7 @@
scope_w = [None, None, None, None]
args.parse_into_scope(None, scope_w, "foo", Signature(["a", "b"], "args", "kw"),
- defaults=Defaults(['x', 'y']))
+ defaults_w=['x', 'y'])
assert len(calls) == 1
assert calls[0] == (None, scope_w, ["a", "b"],
True, True,
@@ -439,7 +438,7 @@
scope_w = [None, None, None, None]
args.parse_into_scope("obj", scope_w, "foo", Signature(["a", "b"],
"args", "kw"),
- defaults=Defaults(['x', 'y']))
+ defaults_w=['x', 'y'])
assert len(calls) == 1
assert calls[0] == ("obj", scope_w, ["a", "b"],
True, True,
@@ -511,25 +510,25 @@
def test_missing_args(self):
# got_nargs, nkwds, expected_nargs, has_vararg, has_kwarg,
# defaults_w, missing_args
- err = ArgErrCount(1, 0, 0, False, False, Defaults([]), 0)
+ err = ArgErrCount(1, 0, 0, False, False, None, 0)
s = err.getmsg('foo')
assert s == "foo() takes no argument (1 given)"
- err = ArgErrCount(0, 0, 1, False, False, Defaults([]), 1)
+ err = ArgErrCount(0, 0, 1, False, False, [], 1)
s = err.getmsg('foo')
assert s == "foo() takes exactly 1 argument (0 given)"
- err = ArgErrCount(3, 0, 2, False, False, Defaults([]), 0)
+ err = ArgErrCount(3, 0, 2, False, False, [], 0)
s = err.getmsg('foo')
assert s == "foo() takes exactly 2 arguments (3 given)"
- err = ArgErrCount(1, 0, 2, True, False, Defaults([]), 1)
+ err = ArgErrCount(1, 0, 2, True, False, [], 1)
s = err.getmsg('foo')
assert s == "foo() takes at least 2 arguments (1 given)"
- err = ArgErrCount(3, 0, 2, True, False, Defaults(['a']), 0)
+ err = ArgErrCount(3, 0, 2, True, False, ['a'], 0)
s = err.getmsg('foo')
assert s == "foo() takes at most 2 arguments (3 given)"
- err = ArgErrCount(0, 1, 2, True, False, Defaults(['a']), 1)
+ err = ArgErrCount(0, 1, 2, True, False, ['a'], 1)
s = err.getmsg('foo')
assert s == "foo() takes at least 1 argument (1 given)"
- err = ArgErrCount(2, 1, 1, False, True, Defaults([]), 0)
+ err = ArgErrCount(2, 1, 1, False, True, [], 0)
s = err.getmsg('foo')
assert s == "foo() takes exactly 1 argument (3 given)"
@@ -603,7 +602,7 @@
args = make_arguments_for_translation(space, [1])
sig = Signature(['a', 'b', 'c'], None, None)
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
@@ -615,25 +614,25 @@
args = make_arguments_for_translation(space, [1], {'c': 3, 'b': 2})
sig = Signature(['a', 'b', 'c'], None, None)
- data = args.match_signature(sig, Defaults([]))
+ data = args.match_signature(sig, [])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
args = make_arguments_for_translation(space, [1], {'c': 5})
sig = Signature(['a', 'b', 'c'], None, None)
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
args = make_arguments_for_translation(space, [1], {'c': 5, 'd': 7})
sig = Signature(['a', 'b', 'c'], None, 'kw')
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
args = make_arguments_for_translation(space, [1,2,3,4,5], {'e': 5, 'd': 7})
sig = Signature(['a', 'b', 'c'], 'r', 'kw')
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
@@ -641,7 +640,7 @@
w_stararg=[1],
w_starstararg={'c': 5, 'd': 7})
sig = Signature(['a', 'b', 'c'], None, 'kw')
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
@@ -649,7 +648,7 @@
w_stararg=[3,4,5],
w_starstararg={'e': 5, 'd': 7})
sig = Signature(['a', 'b', 'c'], 'r', 'kw')
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -4,7 +4,6 @@
from pypy.conftest import gettestobjspace
from pypy.interpreter import gateway, argument
from pypy.interpreter.gateway import ObjSpace, W_Root
-from pypy.interpreter.function import Defaults
import py
import sys
@@ -12,7 +11,7 @@
def __init__(self, space, name):
self.space = space
self.name = name
- self.defs = Defaults([])
+ self.defs_w = []
class TestBuiltinCode:
def test_signature(self):
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -22,7 +22,6 @@
from pypy.interpreter import gateway
from pypy.interpreter.argument import Signature
from pypy.interpreter.buffer import RWBuffer
-from pypy.interpreter.function import Defaults
from pypy.objspace.std.bytearraytype import (
makebytearraydata_w, getbytevalue,
new_bytearray
@@ -43,7 +42,7 @@
registerimplementation(W_BytearrayObject)
init_signature = Signature(['source', 'encoding', 'errors'], None, None)
-init_defaults = Defaults([None, None, None])
+init_defaults = [None, None, None]
def init__Bytearray(space, w_bytearray, __args__):
# this is on the silly side
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -4,7 +4,6 @@
from pypy.interpreter import gateway
from pypy.interpreter.argument import Signature
from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.function import Defaults
from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX, OPTIMIZED_BUILTINS
from pypy.rlib.objectmodel import r_dict, we_are_translated
@@ -617,7 +616,7 @@
init_signature = Signature(['seq_or_map'], None, 'kwargs')
-init_defaults = Defaults([None])
+init_defaults = [None]
def update1(space, w_dict, w_data):
if space.findattr(w_data, space.wrap("keys")) is None:
diff --git a/pypy/objspace/std/fake.py b/pypy/objspace/std/fake.py
--- a/pypy/objspace/std/fake.py
+++ b/pypy/objspace/std/fake.py
@@ -144,7 +144,7 @@
frame = func.space.createframe(self, func.w_func_globals,
func.closure)
sig = self.signature()
- scope_w = args.parse_obj(None, func.name, sig, func.defs.getitems())
+ scope_w = args.parse_obj(None, func.name, sig, func.defs_w)
frame.setfastscope(scope_w)
return frame.run()
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -8,7 +8,6 @@
from pypy.objspace.std import slicetype
from pypy.interpreter import gateway, baseobjspace
-from pypy.interpreter.function import Defaults
from pypy.rlib.listsort import TimSort
from pypy.interpreter.argument import Signature
@@ -33,7 +32,7 @@
init_signature = Signature(['sequence'], None, None)
-init_defaults = Defaults([None])
+init_defaults = [None]
def init__List(space, w_list, __args__):
from pypy.objspace.std.tupleobject import W_TupleObject
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -5,7 +5,6 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import gateway
from pypy.interpreter.argument import Signature
-from pypy.interpreter.function import Defaults
from pypy.objspace.std.settype import set_typedef as settypedef
from pypy.objspace.std.frozensettype import frozenset_typedef as frozensettypedef
@@ -623,7 +622,7 @@
cmp__Frozenset_frozensettypedef = cmp__Set_settypedef
init_signature = Signature(['some_iterable'], None, None)
-init_defaults = Defaults([None])
+init_defaults = [None]
def init__Set(space, w_set, __args__):
w_iterable, = __args__.parse_obj(
None, 'set',
diff --git a/pypy/rpython/callparse.py b/pypy/rpython/callparse.py
--- a/pypy/rpython/callparse.py
+++ b/pypy/rpython/callparse.py
@@ -1,5 +1,4 @@
from pypy.interpreter.argument import ArgumentsForTranslation, ArgErr
-from pypy.interpreter.function import Defaults
from pypy.annotation import model as annmodel
from pypy.rpython import rtuple
from pypy.rpython.error import TyperError
@@ -53,7 +52,7 @@
for x in graph.defaults:
defs_h.append(ConstHolder(x))
try:
- holders = arguments.match_signature(signature, Defaults(defs_h))
+ holders = arguments.match_signature(signature, defs_h)
except ArgErr, e:
raise TyperError, "signature mismatch: %s" % e.getmsg(graph.name)
diff --git a/pypy/translator/geninterplevel.py b/pypy/translator/geninterplevel.py
--- a/pypy/translator/geninterplevel.py
+++ b/pypy/translator/geninterplevel.py
@@ -71,7 +71,7 @@
log = py.log.Producer("geninterp")
py.log.setconsumer("geninterp", ansi_log)
-GI_VERSION = '1.2.8' # bump this for substantial changes
+GI_VERSION = '1.2.9' # bump this for substantial changes
# ____________________________________________________________
try:
@@ -1175,8 +1175,7 @@
pass
defaultsname = self.uniquename('default')
self._defaults_cache[key] = defaultsname
- self.initcode.append("from pypy.interpreter.function import Defaults")
- self.initcode.append("%s = Defaults([%s])" % (defaultsname, ', '.join(names)))
+ self.initcode.append("%s = [%s]" % (defaultsname, ', '.join(names)))
return defaultsname
def gen_rpyfunction(self, func):
From commits-noreply at bitbucket.org Tue May 3 21:51:19 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Tue, 3 May 2011 21:51:19 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: dont call get_cloned() on
values not surviving
Message-ID: <20110503195119.AF9A336C204@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43867:2e08608edf8b
Date: 2011-05-03 21:50 +0200
http://bitbucket.org/pypy/pypy/changeset/2e08608edf8b/
Log: dont call get_cloned() on values not surviving
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
@@ -363,8 +363,9 @@
new.producer = self.producer
assert self.posponedop is None
- for box, value in self.values.items():
+ for box in short_boxes.keys() + surviving_boxes:
box = new.getinterned(box)
+ value = self.getvalue(box)
force = box in surviving_boxes
value = value.get_cloned(new, valuemap,
force_if_needed=force)
diff --git a/pypy/jit/metainterp/test/test_string.py b/pypy/jit/metainterp/test/test_string.py
--- a/pypy/jit/metainterp/test/test_string.py
+++ b/pypy/jit/metainterp/test/test_string.py
@@ -461,6 +461,26 @@
return sa
assert self.meta_interp(f, [16, 'a']) == f(16, 'a')
+ def test_boxed_virtual_string_not_surviving(self):
+ class StrBox(object):
+ def __init__(self, val):
+ self.val = val
+ class IntBox(object):
+ def __init__(self, val):
+ self.val = val
+ _str = self._str
+ mydriver = JitDriver(reds = ['i', 'nt', 'sa'], greens = [])
+ def f(c):
+ nt = StrBox(_str(c*16))
+ sa = StrBox(_str(''))
+ i = IntBox(0)
+ while i.val < len(nt.val):
+ mydriver.jit_merge_point(i=i, nt=nt, sa=sa)
+ sa = StrBox(sa.val + StrBox(nt.val[i.val]).val)
+ i = IntBox(i.val + 1)
+ return len(sa.val)
+ assert self.meta_interp(f, ['a']) == f('a')
+
#class TestOOtype(StringTests, OOJitMixin):
# CALL = "oosend"
# CALL_PURE = "oosend_pure"
From commits-noreply at bitbucket.org Wed May 4 00:10:06 2011
From: commits-noreply at bitbucket.org (gutworth)
Date: Wed, 4 May 2011 00:10:06 +0200 (CEST)
Subject: [pypy-svn] pypy default: bumping the extended_arg_count is not
equivalent to reresolving jump targets
Message-ID: <20110503221006.B2C9836C205@codespeak.net>
Author: Benjamin Peterson
Branch:
Changeset: r43872:edd199709433
Date: 2011-05-03 17:11 -0500
http://bitbucket.org/pypy/pypy/changeset/edd199709433/
Log: bumping the extended_arg_count is not equivalent to reresolving jump
targets
This should fix issue #713.
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -286,6 +286,7 @@
while True:
extended_arg_count = 0
offset = 0
+ force_redo = False
# Calculate the code offset of each block.
for block in blocks:
block.offset = offset
@@ -313,7 +314,7 @@
instr.has_jump = False
# The size of the code changed,
# we have to trigger another pass
- extended_arg_count += 1
+ force_redo = True
continue
if absolute:
jump_arg = target.offset
@@ -322,7 +323,7 @@
instr.arg = jump_arg
if jump_arg > 0xFFFF:
extended_arg_count += 1
- if extended_arg_count == last_extended_arg_count:
+ if extended_arg_count == last_extended_arg_count and not force_redo:
break
else:
last_extended_arg_count = extended_arg_count
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -73,6 +73,10 @@
def error_test(self, source, exc_type):
py.test.raises(exc_type, self.simple_test, source, None, None)
+ def test_issue_713(self):
+ func = "def f(_=2): return (_ if _ else _) if False else _"
+ yield self.st, func, "f()", 2
+
def test_long_jump(self):
func = """def f(x):
y = 0
From commits-noreply at bitbucket.org Wed May 4 00:27:15 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Wed, 4 May 2011 00:27:15 +0200 (CEST)
Subject: [pypy-svn] pypy default: Use StringBuilder to avoid double copy in
str.translate
Message-ID: <20110503222715.D01DD36C205@codespeak.net>
Author: Alex Gaynor
Branch:
Changeset: r43873:371d4fa9e108
Date: 2011-05-03 18:25 -0400
http://bitbucket.org/pypy/pypy/changeset/371d4fa9e108/
Log: Use StringBuilder to avoid double copy in str.translate
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -963,19 +963,20 @@
space.wrap("translation table must be 256 characters long"))
string = w_string._value
- chars = []
deletechars = space.str_w(w_deletechars)
if len(deletechars) == 0:
+ buf = StringBuilder(len(string))
for char in string:
- chars.append(table[ord(char)])
+ buf.append(table[ord(char)])
else:
+ buf = StringBuilder()
deletion_table = [False] * 256
for c in deletechars:
deletion_table[ord(c)] = True
for char in string:
if not deletion_table[ord(char)]:
- chars.append(table[ord(char)])
- return W_StringObject(''.join(chars))
+ buf.append(table[ord(char)])
+ return W_StringObject(buf.build())
def str_decode__String_ANY_ANY(space, w_string, w_encoding=None, w_errors=None):
from pypy.objspace.std.unicodetype import _get_encoding_and_errors, \
From commits-noreply at bitbucket.org Wed May 4 00:27:17 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Wed, 4 May 2011 00:27:17 +0200 (CEST)
Subject: [pypy-svn] pypy default: merged upstream
Message-ID: <20110503222717.12EAE36C205@codespeak.net>
Author: Alex Gaynor
Branch:
Changeset: r43874:348a613f12aa
Date: 2011-05-03 18:26 -0400
http://bitbucket.org/pypy/pypy/changeset/348a613f12aa/
Log: merged upstream
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -286,6 +286,7 @@
while True:
extended_arg_count = 0
offset = 0
+ force_redo = False
# Calculate the code offset of each block.
for block in blocks:
block.offset = offset
@@ -313,7 +314,7 @@
instr.has_jump = False
# The size of the code changed,
# we have to trigger another pass
- extended_arg_count += 1
+ force_redo = True
continue
if absolute:
jump_arg = target.offset
@@ -322,7 +323,7 @@
instr.arg = jump_arg
if jump_arg > 0xFFFF:
extended_arg_count += 1
- if extended_arg_count == last_extended_arg_count:
+ if extended_arg_count == last_extended_arg_count and not force_redo:
break
else:
last_extended_arg_count = extended_arg_count
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -73,6 +73,10 @@
def error_test(self, source, exc_type):
py.test.raises(exc_type, self.simple_test, source, None, None)
+ def test_issue_713(self):
+ func = "def f(_=2): return (_ if _ else _) if False else _"
+ yield self.st, func, "f()", 2
+
def test_long_jump(self):
func = """def f(x):
y = 0
From commits-noreply at bitbucket.org Wed May 4 03:47:13 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Wed, 4 May 2011 03:47:13 +0200 (CEST)
Subject: [pypy-svn] pypy default: Remove rlib.rstring.repeat_string,
replace with normal * operator for rstrings,
also improved the efficiency (only one allocation,
and log(n) copies).
Message-ID: <20110504014713.3E196282B89@codespeak.net>
Author: Alex Gaynor
Branch:
Changeset: r43875:6724e4b85bed
Date: 2011-05-03 21:46 -0400
http://bitbucket.org/pypy/pypy/changeset/6724e4b85bed/
Log: Remove rlib.rstring.repeat_string, replace with normal * operator
for rstrings, also improved the efficiency (only one allocation, and
log(n) copies).
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
@@ -43,8 +43,8 @@
class TestAnnotateTestCase:
- def setup_class(cls):
- cls.space = FlowObjSpace()
+ def setup_class(cls):
+ cls.space = FlowObjSpace()
def teardown_method(self, meth):
assert annmodel.s_Bool == annmodel.SomeBool()
@@ -263,7 +263,7 @@
getcdef = a.bookkeeper.getuniqueclassdef
assert getcdef(snippet.F).attrs.keys() == ['m']
assert getcdef(snippet.G).attrs.keys() == ['m2']
- assert getcdef(snippet.H).attrs.keys() == ['attr']
+ assert getcdef(snippet.H).attrs.keys() == ['attr']
assert getcdef(snippet.H).about_attribute('attr') == (
a.bookkeeper.immutablevalue(1))
@@ -390,34 +390,34 @@
def test_tuple_unpack_from_const_tuple_with_different_types(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.func_arg_unpack, [])
- assert isinstance(s, annmodel.SomeInteger)
- assert s.const == 3
+ assert isinstance(s, annmodel.SomeInteger)
+ assert s.const == 3
def test_pbc_attr_preserved_on_instance(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.preserve_pbc_attr_on_instance, [bool])
#a.simplify()
#a.translator.view()
- assert s == annmodel.SomeInteger(nonneg=True)
- #self.assertEquals(s.__class__, annmodel.SomeInteger)
+ assert s == annmodel.SomeInteger(nonneg=True)
+ #self.assertEquals(s.__class__, annmodel.SomeInteger)
def test_pbc_attr_preserved_on_instance_with_slots(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.preserve_pbc_attr_on_instance_with_slots,
[bool])
- assert s == annmodel.SomeInteger(nonneg=True)
-
- def test_is_and_knowntype_data(self):
+ assert s == annmodel.SomeInteger(nonneg=True)
+
+ def test_is_and_knowntype_data(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.is_and_knowntype, [str])
#a.simplify()
#a.translator.view()
assert s == a.bookkeeper.immutablevalue(None)
- def test_isinstance_and_knowntype_data(self):
+ def test_isinstance_and_knowntype_data(self):
a = self.RPythonAnnotator()
x = a.bookkeeper.immutablevalue(snippet.apbc)
- s = a.build_types(snippet.isinstance_and_knowntype, [x])
+ s = a.build_types(snippet.isinstance_and_knowntype, [x])
#a.simplify()
#a.translator.view()
assert s == x
@@ -434,8 +434,8 @@
# the annotator (it doesn't check that they operate property, though)
for example, methname, s_example in [
('', 'join', annmodel.SomeString()),
- ([], 'append', somelist()),
- ([], 'extend', somelist()),
+ ([], 'append', somelist()),
+ ([], 'extend', somelist()),
([], 'reverse', somelist()),
([], 'insert', somelist()),
([], 'pop', somelist()),
@@ -465,6 +465,13 @@
assert isinstance(s, annmodel.SomeList)
assert s.listdef.listitem.resized
+ def test_str_mul(self):
+ a = self.RPythonAnnotator()
+ def f(a_str):
+ return a_str * 3
+ s = a.build_types(f, [str])
+ assert isinstance(s, annmodel.SomeString)
+
def test_simple_slicing(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.simple_slice, [list])
@@ -474,7 +481,7 @@
a = self.RPythonAnnotator()
s = a.build_types(snippet.simple_iter, [list])
assert isinstance(s, annmodel.SomeIterator)
-
+
def test_simple_iter_next(self):
def f(x):
i = iter(range(x))
@@ -498,7 +505,7 @@
assert listitem(s).knowntype == tuple
assert listitem(s).items[0].knowntype == int
assert listitem(s).items[1].knowntype == str
-
+
def test_dict_copy(self):
a = self.RPythonAnnotator()
t = somedict(annmodel.SomeInteger(), annmodel.SomeInteger())
@@ -544,7 +551,7 @@
a = self.RPythonAnnotator()
s = a.build_types(snippet.dict_values, [])
assert isinstance(listitem(s), annmodel.SomeString)
-
+
def test_dict_values2(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.dict_values2, [])
@@ -570,19 +577,19 @@
assert isinstance(dictkey(s), annmodel.SomeString)
assert isinstance(dictvalue(s), annmodel.SomeInteger)
assert not dictvalue(s).nonneg
-
+
def test_exception_deduction(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.exception_deduction, [])
assert isinstance(s, annmodel.SomeInstance)
assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
-
+
def test_exception_deduction_we_are_dumb(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.exception_deduction_we_are_dumb, [])
assert isinstance(s, annmodel.SomeInstance)
assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
-
+
def test_nested_exception_deduction(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.nested_exception_deduction, [])
@@ -645,8 +652,8 @@
assert Rdef.attrs['r'].s_value.classdef == Rdef
assert Rdef.attrs['n'].s_value.knowntype == int
assert Rdef.attrs['m'].s_value.knowntype == int
-
-
+
+
def test_propagation_of_fresh_instances_through_attrs_rec_eo(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.make_eo, [int])
@@ -958,7 +965,7 @@
f1(1,2)
g(f2)
g(f3)
-
+
a = self.RPythonAnnotator()
s = a.build_types(h, [])
@@ -1022,7 +1029,7 @@
famA_m = mdescA_m.getcallfamily()
famC_m = mdescC_m.getcallfamily()
famB_n = mdescB_n.getcallfamily()
-
+
assert famA_m is famC_m
assert famB_n is not famA_m
@@ -1038,7 +1045,7 @@
gfCinit = graphof(a, C.__init__.im_func)
assert famCinit.calltables == {(1, (), False, False): [{mdescCinit.funcdesc: gfCinit}] }
-
+
def test_isinstance_usigned(self):
def f(x):
return isinstance(x, r_uint)
@@ -1085,7 +1092,7 @@
s = a.build_types(f, [])
C1df = a.bookkeeper.getuniqueclassdef(C1)
C2df = a.bookkeeper.getuniqueclassdef(C2)
-
+
assert s.items[0].classdef == C1df
assert s.items[1].classdef == C2df
@@ -1098,29 +1105,29 @@
assert a.binding(graph2.getreturnvar()).classdef == C2df
assert graph1 in a.translator.graphs
assert graph2 in a.translator.graphs
-
+
def test_specialcase_args(self):
class C1(object):
pass
-
+
class C2(object):
pass
-
+
def alloc(cls, cls2):
i = cls()
assert isinstance(i, cls)
j = cls2()
assert isinstance(j, cls2)
return i
-
+
def f():
alloc(C1, C1)
alloc(C1, C2)
alloc(C2, C1)
alloc(C2, C2)
-
+
alloc._annspecialcase_ = "specialize:arg(0,1)"
-
+
a = self.RPythonAnnotator()
C1df = a.bookkeeper.getuniqueclassdef(C1)
C2df = a.bookkeeper.getuniqueclassdef(C2)
@@ -1180,9 +1187,9 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [int, int])
-
+
executedesc = a.bookkeeper.getdesc(I.execute.im_func)
- assert len(executedesc._cache) == 2
+ assert len(executedesc._cache) == 2
assert len(executedesc._cache[(0, 'star', 2)].startblock.inputargs) == 4
assert len(executedesc._cache[(1, 'star', 3)].startblock.inputargs) == 5
@@ -1201,7 +1208,7 @@
s_item = listitem(s)
assert isinstance(s_item, annmodel.SomeInstance)
assert s_item.classdef is a.bookkeeper.getuniqueclassdef(T)
-
+
def test_assert_type_is_list_doesnt_lose_info(self):
class T(object):
pass
@@ -1254,7 +1261,7 @@
x = bool(l)
l.append(1)
return x, bool(l)
-
+
a = self.RPythonAnnotator()
s = a.build_types(f, [])
assert s.const == False
@@ -1264,7 +1271,7 @@
assert s.items[0].knowntype == bool and not s.items[0].is_constant()
assert s.items[1].knowntype == bool and not s.items[1].is_constant()
-
+
def test_empty_dict(self):
def f():
d = {}
@@ -1274,7 +1281,7 @@
x = bool(d)
d['a'] = 1
return x, bool(d)
-
+
a = self.RPythonAnnotator()
s = a.build_types(f, [])
assert s.const == False
@@ -1534,7 +1541,7 @@
def witness1(x):
pass
def witness2(x):
- pass
+ pass
def f(x):
if 0 < x:
witness1(x)
@@ -1543,15 +1550,15 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [annmodel.SomeInteger(unsigned=True)])
wg1 = graphof(a, witness1)
- wg2 = graphof(a, witness2)
+ wg2 = graphof(a, witness2)
assert a.binding(wg1.getargs()[0]).unsigned is True
- assert a.binding(wg2.getargs()[0]).unsigned is True
-
+ assert a.binding(wg2.getargs()[0]).unsigned is True
+
def test_general_nonneg_cleverness_is_gentle_with_unsigned(self):
def witness1(x):
pass
def witness2(x):
- pass
+ pass
def f(x):
if 0 < x:
witness1(x)
@@ -1560,7 +1567,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [annmodel.SomeInteger(knowntype=r_ulonglong)])
wg1 = graphof(a, witness1)
- wg2 = graphof(a, witness2)
+ wg2 = graphof(a, witness2)
assert a.binding(wg1.getargs()[0]).knowntype is r_ulonglong
assert a.binding(wg2.getargs()[0]).knowntype is r_ulonglong
@@ -1742,11 +1749,11 @@
assert s.const == "bool"
a = self.RPythonAnnotator()
s = a.build_types(f, [int])
- assert s.const == "int"
+ assert s.const == "int"
a = self.RPythonAnnotator()
s = a.build_types(f, [float])
- assert s.const == "dontknow"
-
+ assert s.const == "dontknow"
+
def test_hidden_method(self):
class Base:
def method(self):
@@ -1825,7 +1832,7 @@
s = a.build_types(f, [])
assert s.knowntype == bool
assert not s.is_constant()
-
+
def test_const_dict_and_none(self):
def g(d=None):
return d is None
@@ -1837,7 +1844,7 @@
s = a.build_types(f, [])
assert s.knowntype == bool
assert not s.is_constant()
-
+
def test_issubtype_and_const(self):
class A(object):
pass
@@ -1951,7 +1958,7 @@
a = annrpython.RPythonAnnotator()
from pypy.annotation import model as annmodel
- s_f = a.bookkeeper.immutablevalue(f)
+ s_f = a.bookkeeper.immutablevalue(f)
a.bookkeeper.emulate_pbc_call('f', s_f, [annmodel.SomeInteger(), annmodel.SomeInteger()])
a.complete()
@@ -1960,7 +1967,7 @@
someint = annmodel.SomeInteger()
- assert (fdesc.get_s_signatures((2,(),False,False))
+ assert (fdesc.get_s_signatures((2,(),False,False))
== [([someint,someint],someint)])
def test_emulated_pbc_call_callback(self):
@@ -1974,7 +1981,7 @@
def callb(ann, graph):
memo.append(annmodel.SomeInteger() == ann.binding(graph.getreturnvar()))
- s_f = a.bookkeeper.immutablevalue(f)
+ s_f = a.bookkeeper.immutablevalue(f)
s = a.bookkeeper.emulate_pbc_call('f', s_f, [annmodel.SomeInteger(), annmodel.SomeInteger()],
callback=callb)
assert s == annmodel.SomeImpossibleValue()
@@ -1996,7 +2003,7 @@
s = a.build_types(f, [])
assert isinstance(s, annmodel.SomeIterator)
assert s.variant == ('items',)
-
+
def test_non_none_and_none_with_isinstance(self):
class A(object):
pass
@@ -2230,7 +2237,7 @@
def f(i):
witness(None)
return witness(get(i))
-
+
a = self.RPythonAnnotator()
s = a.build_types(f, [int])
assert s.__class__ == annmodel.SomeObject
@@ -2284,8 +2291,8 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [])
assert isinstance(s.items[0], annmodel.SomeInteger)
- assert isinstance(s.items[1], annmodel.SomeChar)
- assert isinstance(s.items[2], annmodel.SomeChar)
+ assert isinstance(s.items[1], annmodel.SomeChar)
+ assert isinstance(s.items[2], annmodel.SomeChar)
def test___class___attribute(self):
class Base(object): pass
@@ -2344,7 +2351,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [bool])
assert s.knowntype == int
-
+
def f(x):
return -x
@@ -2394,7 +2401,7 @@
assert isinstance(s, annmodel.SomeInteger)
assert s.knowntype == inttype
assert s.unsigned == (inttype(-1) > 0)
-
+
for inttype in inttypes:
def f():
return inttype(0)
@@ -2493,11 +2500,11 @@
def test_helper_method_annotator(self):
def fun():
return 21
-
+
class A(object):
def helper(self):
return 42
-
+
a = self.RPythonAnnotator()
a.build_types(fun, [])
a.annotate_helper_method(A, "helper", [])
@@ -2794,7 +2801,7 @@
def c(x):
return int(x)
-
+
def g(a, x):
if x == -1:
a = None
@@ -2806,7 +2813,7 @@
x = x + .01
return a(x)
- #def fun(x):
+ #def fun(x):
a = self.RPythonAnnotator(policy=policy.AnnotatorPolicy())
s = a.build_types(g, [annmodel.SomeGenericCallable(
@@ -2845,7 +2852,7 @@
class B(A):
def meth(self):
return self
- class C(A):
+ class C(A):
def meth(self):
return self
@@ -2893,7 +2900,7 @@
i.x = x
a = self.RPythonAnnotator()
- py.test.raises(Exception, a.build_types, f, [])
+ py.test.raises(Exception, a.build_types, f, [])
class M:
@@ -2910,30 +2917,30 @@
self.l2 = []
c = C()
-
+
def f():
x = A()
x = hint(x, access_directly=True)
c.m.l.append(x)
a = self.RPythonAnnotator()
- py.test.raises(AssertionError, a.build_types, f, [])
+ py.test.raises(AssertionError, a.build_types, f, [])
def f():
x = A()
x = hint(x, access_directly=True)
c.m.d[None] = x
-
+
a = self.RPythonAnnotator()
- py.test.raises(AssertionError, a.build_types, f, [])
+ py.test.raises(AssertionError, a.build_types, f, [])
def f():
x = A()
x = hint(x, access_directly=True)
c.m.d[x] = None
-
+
a = self.RPythonAnnotator()
- py.test.raises(AssertionError, a.build_types, f, [])
+ py.test.raises(AssertionError, a.build_types, f, [])
def test_ctr_location(self):
from pypy.rlib.jit import hint
@@ -3026,7 +3033,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [])
- assert isinstance(s, annmodel.SomeUnicodeString)
+ assert isinstance(s, annmodel.SomeUnicodeString)
def test_unicode(self):
def g(n):
@@ -3091,7 +3098,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [str])
assert isinstance(s, annmodel.SomeString)
-
+
def f(x):
return u'a'.replace(x, u'b')
@@ -3105,7 +3112,7 @@
if c == i:
return c
return 'x'
-
+
a = self.RPythonAnnotator()
s = a.build_types(f, [unicode, str])
assert isinstance(s, annmodel.SomeUnicodeCodePoint)
@@ -3113,22 +3120,22 @@
def test_strformatting_unicode(self):
def f(x):
return '%s' % unichr(x)
-
+
a = self.RPythonAnnotator()
py.test.raises(NotImplementedError, a.build_types, f, [int])
def f(x):
return '%s' % (unichr(x) * 3)
-
+
a = self.RPythonAnnotator()
py.test.raises(NotImplementedError, a.build_types, f, [int])
def f(x):
return '%s%s' % (1, unichr(x))
-
+
a = self.RPythonAnnotator()
py.test.raises(NotImplementedError, a.build_types, f, [int])
def f(x):
return '%s%s' % (1, unichr(x) * 15)
-
+
a = self.RPythonAnnotator()
py.test.raises(NotImplementedError, a.build_types, f, [int])
@@ -3197,7 +3204,7 @@
called.append(True)
assert not ann.listdef.listitem.mutated
ann.listdef.never_resize()
-
+
def f():
l = [1,2,3]
check_annotation(l, checker)
@@ -3213,7 +3220,7 @@
def test_listitem_no_mutating2(self):
from pypy.rlib.debug import make_sure_not_resized
-
+
def f():
return make_sure_not_resized([1,2,3])
@@ -3293,11 +3300,11 @@
return d1[x].meth()
d1[i+1] = A()
return 0
-
+
a = self.RPythonAnnotator()
s = a.build_types(g, [int, int])
assert s.knowntype is int
-
+
def f(x):
d0 = {}
if x in d0:
@@ -3476,7 +3483,7 @@
return total
constant_unsigned_five = r_uint(5)
-
+
class Freezing:
def _freeze_(self):
return True
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -11,7 +11,7 @@
from pypy.objspace.std.listobject import W_ListObject
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.tupleobject import W_TupleObject
-from pypy.rlib.rstring import StringBuilder, string_repeat
+from pypy.rlib.rstring import StringBuilder
from pypy.interpreter.buffer import StringBuffer
from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
@@ -856,7 +856,7 @@
if len(input) == 1:
s = input[0] * mul
else:
- s = string_repeat(input, mul)
+ s = input * mul
# xxx support again space.config.objspace.std.withstrjoin?
return W_StringObject(s)
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -11,7 +11,7 @@
from pypy.objspace.std.tupleobject import W_TupleObject
from pypy.rlib.rarithmetic import intmask, ovfcheck
from pypy.rlib.objectmodel import compute_hash
-from pypy.rlib.rstring import UnicodeBuilder, string_repeat
+from pypy.rlib.rstring import UnicodeBuilder
from pypy.rlib.runicode import unicode_encode_unicode_escape
from pypy.module.unicodedata import unicodedb
from pypy.tool.sourcetools import func_with_new_name
@@ -278,7 +278,7 @@
if len(input) == 1:
result = input[0] * times
else:
- result = string_repeat(input, times)
+ result = input * times
return W_UnicodeObject(result)
def mul__ANY_Unicode(space, w_times, w_uni):
diff --git a/pypy/rlib/rstring.py b/pypy/rlib/rstring.py
--- a/pypy/rlib/rstring.py
+++ b/pypy/rlib/rstring.py
@@ -3,7 +3,6 @@
from pypy.annotation.model import SomeObject, SomeString, s_None,\
SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString
-from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.extregistry import ExtRegistryEntry
@@ -79,32 +78,6 @@
tp = unicode
-# XXX: This does log(mul) mallocs, the GCs probably make that efficient, but
-# some measurement should be done at some point.
-def string_repeat(s, mul):
- """Repeat a string or unicode. Note that this assumes that 'mul' > 0."""
- result = None
- factor = 1
- assert mul > 0
- try:
- ovfcheck(len(s) * mul)
- except OverflowError:
- raise MemoryError
-
- limit = mul >> 1
- while True:
- if mul & factor:
- if result is None:
- result = s
- else:
- result = s + result
- if factor > limit:
- break
- s += s
- factor *= 2
- return result
-string_repeat._annspecialcase_ = 'specialize:argtype(0)'
-
# ------------------------------------------------------------
# ----------------- implementation details -------------------
# ------------------------------------------------------------
@@ -159,7 +132,7 @@
def method_build(self):
return SomeUnicodeString()
-
+
def rtyper_makerepr(self, rtyper):
return rtyper.type_system.rbuilder.unicodebuilder_repr
@@ -170,7 +143,7 @@
if self.use_unicode:
return SomeUnicodeBuilder()
return SomeStringBuilder()
-
+
def specialize_call(self, hop):
return hop.r_result.rtyper_new(hop)
diff --git a/pypy/rlib/test/test_rstring.py b/pypy/rlib/test/test_rstring.py
--- a/pypy/rlib/test/test_rstring.py
+++ b/pypy/rlib/test/test_rstring.py
@@ -1,7 +1,6 @@
import sys
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit, \
- string_repeat
+from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit
def test_split():
@@ -43,7 +42,4 @@
assert s.getlength() == len('aabcb')
s.append_multiple_char(u'd', 4)
assert s.build() == 'aabcbdddd'
- assert isinstance(s.build(), unicode)
-
-def test_string_repeat():
- raises(MemoryError, string_repeat, "abc", sys.maxint)
+ assert isinstance(s.build(), unicode)
\ 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
@@ -5,6 +5,7 @@
from pypy.rlib.objectmodel import _hash_string, enforceargs
from pypy.rlib.debug import ll_assert
from pypy.rlib.jit import purefunction, we_are_jitted
+from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.robject import PyObjRepr, pyobj_repr
from pypy.rpython.rmodel import inputconst, IntegerRepr
from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
@@ -255,6 +256,27 @@
class LLHelpers(AbstractLLHelpers):
+ @purefunction
+ def ll_str_mul(s, times):
+ if times < 0:
+ times = 0
+ try:
+ size = ovfcheck(len(s.chars) * times)
+ except OverflowError:
+ raise MemoryError
+ newstr = s.malloc(size)
+ i = 0
+ if i < size:
+ s.copy_contents(s, newstr, 0, 0, len(s.chars))
+ i += len(s.chars)
+ while i < size:
+ if i <= size - i:
+ j = i
+ else:
+ j = size - i
+ s.copy_contents(newstr, newstr, 0, i, j)
+ i += j
+ return newstr
@purefunction
def ll_char_mul(ch, times):
diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -1,4 +1,5 @@
from pypy.tool.pairtype import pairtype
+from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.error import TyperError
from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
AbstractUniCharRepr, AbstractStringIteratorRepr,\
@@ -134,6 +135,19 @@
i+= 1
return buf.ll_build()
+ def ll_str_mul(s, times):
+ if times < 0:
+ times = 0
+ try:
+ size = ovfcheck(s.ll_strlen() * times)
+ except OverflowError:
+ raise MemoryError
+ buf = ootype.new(typeOf(s).builder)
+ buf.ll_allocate(size)
+ for i in xrange(times):
+ buf.ll_append(s)
+ return buf.ll_build()
+
def ll_streq(s1, s2):
if s1 is None:
return s2 is None
@@ -203,7 +217,7 @@
return s.ll_substring(start, s.ll_strlen() - start)
def ll_stringslice_startstop(s, start, stop):
- length = s.ll_strlen()
+ length = s.ll_strlen()
if stop > length:
stop = length
return s.ll_substring(start, stop-start)
@@ -265,7 +279,7 @@
def ll_float(ll_str):
return ootype.ooparse_float(ll_str)
-
+
# interface to build strings:
# x = ll_build_start(n)
# ll_build_push(x, next_string, 0)
@@ -300,7 +314,7 @@
c8 = hop.inputconst(ootype.Signed, 8)
c10 = hop.inputconst(ootype.Signed, 10)
c16 = hop.inputconst(ootype.Signed, 16)
- c_StringBuilder = hop.inputconst(ootype.Void, ootype.StringBuilder)
+ c_StringBuilder = hop.inputconst(ootype.Void, ootype.StringBuilder)
v_buf = hop.genop("new", [c_StringBuilder], resulttype=ootype.StringBuilder)
things = cls.parse_fmt_string(s)
@@ -334,7 +348,7 @@
hop.genop('oosend', [c_append, v_buf, vchunk], resulttype=ootype.Void)
hop.exception_cannot_occur() # to ignore the ZeroDivisionError of '%'
- return hop.genop('oosend', [c_build, v_buf], resulttype=ootype.String)
+ return hop.genop('oosend', [c_build, v_buf], resulttype=ootype.String)
do_stringformat = classmethod(do_stringformat)
@@ -399,7 +413,7 @@
return iter
def ll_strnext(iter):
- string = iter.string
+ string = iter.string
index = iter.index
if index >= string.ll_strlen():
raise StopIteration
diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -34,7 +34,7 @@
class __extend__(annmodel.SomeUnicodeString):
def rtyper_makerepr(self, rtyper):
return rtyper.type_system.rstr.unicode_repr
-
+
def rtyper_makekey(self):
return self.__class__,
@@ -164,7 +164,7 @@
v_str, = hop.inputargs(string_repr)
hop.exception_cannot_occur()
return hop.gendirectcall(self.ll.ll_upper, v_str)
-
+
def rtype_method_lower(self, hop):
string_repr = hop.args_r[0].repr
v_str, = hop.inputargs(string_repr)
@@ -361,6 +361,17 @@
rtype_getitem_idx_key = rtype_getitem_idx
+ def rtype_mul((r_str, r_int), hop):
+ str_repr = r_str.repr
+ v_str, v_int = hop.inputargs(str_repr, Signed)
+ return hop.gendirectcall(r_str.ll.ll_str_mul, v_str, v_int)
+ rtype_inplace_mul = rtype_mul
+
+class __extend__(pairtype(IntegerRepr, AbstractStringRepr)):
+ def rtype_mul((r_int, r_str), hop):
+ return pair(r_str, r_int).rtype_mul(hop)
+ rtype_inplace_mul = rtype_mul
+
class __extend__(AbstractStringRepr):
@@ -384,7 +395,7 @@
def rtype_eq((r_str1, r_str2), hop):
v_str1, v_str2 = hop.inputargs(r_str1.repr, r_str2.repr)
return hop.gendirectcall(r_str1.ll.ll_streq, v_str1, v_str2)
-
+
def rtype_ne((r_str1, r_str2), hop):
v_str1, v_str2 = hop.inputargs(r_str1.repr, r_str2.repr)
vres = hop.gendirectcall(r_str1.ll.ll_streq, v_str1, v_str2)
@@ -465,7 +476,7 @@
return value
def get_ll_eq_function(self):
- return None
+ return None
def get_ll_hash_function(self):
return self.ll.ll_char_hash
@@ -505,7 +516,7 @@
class __extend__(pairtype(AbstractCharRepr, IntegerRepr),
pairtype(AbstractUniCharRepr, IntegerRepr)):
-
+
def rtype_mul((r_chr, r_int), hop):
char_repr = r_chr.char_repr
v_char, v_int = hop.inputargs(char_repr, Signed)
@@ -545,7 +556,7 @@
return value
def get_ll_eq_function(self):
- return None
+ return None
def get_ll_hash_function(self):
return self.ll.ll_unichar_hash
diff --git a/pypy/rpython/test/test_rstr.py b/pypy/rpython/test/test_rstr.py
--- a/pypy/rpython/test/test_rstr.py
+++ b/pypy/rpython/test/test_rstr.py
@@ -88,7 +88,7 @@
for i in range(3):
res = self.interpret(fn, [i])
assert res is True
-
+
def test_char_constant(self):
const = self.const
def fn(s):
@@ -141,6 +141,16 @@
res = self.interpret(fn, [const('5'), 3])
assert res == 5551
+ def test_str_mul(self):
+ const = self.const
+ def fn(i, mul):
+ s = ["", "a", "aba"][i]
+ return s * mul
+ for i in xrange(3):
+ for m in [0, 1, 4]:
+ res = self.interpret(fn, [i, m])
+ assert self.ll_to_string(res) == fn(i, m)
+
def test_is_none(self):
const = self.const
def fn(i):
@@ -295,7 +305,7 @@
for i, expected in enumerate([0, 1110, 2220, 3330, -1110, -1110]):
res = self.interpret(f, [i])
assert res == expected
-
+
def test_rfind(self):
const = self.const
def fn():
@@ -531,7 +541,7 @@
assert res.find('>, much nicer than , much nicer than
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43876:095d2f5d05df
Date: 2011-05-04 08:34 +0200
http://bitbucket.org/pypy/pypy/changeset/095d2f5d05df/
Log: dont allow constant boxes to be represented by a non surviving box
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
@@ -344,17 +344,21 @@
if surviving_boxes is None:
surviving_boxes = []
+ for box in surviving_boxes:
+ if box not in short_boxes:
+ short_boxes[box] = None
+
valuemap = {}
new = Optimizer(self.metainterp_sd, self.loop)
- optimizations = [o.reconstruct_for_next_iteration(short_boxes, surviving_boxes,
+ optimizations = [o.reconstruct_for_next_iteration(short_boxes,
+ surviving_boxes,
new, valuemap)
for o in self.optimizations]
new.set_optimizations(optimizations)
- new.interned_refs = self.interned_refs # Constants
- new.bool_boxes = {} # Flags values as bools
- for value in new.bool_boxes.keys():
- new.bool_boxes[value.get_cloned(new, valuemap)] = None
+ for value, box in self.interned_refs.items():
+ if box in short_boxes:
+ new.interned_refs[value] = box
new.pure_operations = args_dict()
for key, op in self.pure_operations.items():
@@ -363,15 +367,18 @@
new.producer = self.producer
assert self.posponedop is None
- for box in short_boxes.keys() + surviving_boxes:
+ for box in short_boxes:
box = new.getinterned(box)
value = self.getvalue(box)
+ bool_box = value in self.bool_boxes
force = box in surviving_boxes
value = value.get_cloned(new, valuemap,
force_if_needed=force)
if value is not None:
new.values[box] = value
-
+ if bool_box:
+ new.bool_boxes[value] = None
+
return new
def produce_potential_short_preamble_ops(self, potential_ops):
@@ -387,6 +394,7 @@
short_boxes = {}
for box in inputargs:
short_boxes[box] = None
+
for box in potential_ops.keys():
try:
self.produce_short_preamble_box(box, short_boxes,
From commits-noreply at bitbucket.org Wed May 4 11:56:33 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 11:56:33 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: remove bad merge
Message-ID: <20110504095633.4101A282B89@codespeak.net>
Author: Maciej Fijalkowski
Branch: numpy-exp
Changeset: r43878:8100e72b756e
Date: 2011-05-04 11:48 +0200
http://bitbucket.org/pypy/pypy/changeset/8100e72b756e/
Log: remove bad merge
diff --git a/pypy/jit/tl/pypyjit_demo.py b/pypy/jit/tl/pypyjit_demo.py
--- a/pypy/jit/tl/pypyjit_demo.py
+++ b/pypy/jit/tl/pypyjit_demo.py
@@ -1,26 +1,10 @@
try:
-<<<<<<< local
import numpy
a = numpy.array(range(10))
b = a + a + a
print b[3]
-=======
- def g(x):
- return x - 1
- def f(x):
- while x:
- x = g(x)
- import cProfile
- import time
- t1 = time.time()
- cProfile.run("f(10000000)")
- t2 = time.time()
- f(10000000)
- t3 = time.time()
- print t2 - t1, t3 - t2, (t3 - t2) / (t2 - t1)
->>>>>>> other
except Exception, e:
print "Exception: ", type(e)
print e
From commits-noreply at bitbucket.org Wed May 4 12:05:33 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 12:05:33 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Try to revert the vector ops. will do it
differently
Message-ID: <20110504100533.310BA282B89@codespeak.net>
Author: Maciej Fijalkowski
Branch: numpy-exp
Changeset: r43879:87a7b0aeccfc
Date: 2011-05-04 12:03 +0200
http://bitbucket.org/pypy/pypy/changeset/87a7b0aeccfc/
Log: Try to revert the vector ops. will do it differently
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
@@ -351,8 +351,6 @@
prepare = self._handle_jit_call
elif oopspec_name.startswith('libffi_'):
prepare = self._handle_libffi_call
- elif oopspec_name.startswith('vector_'):
- prepare = self._handle_vector_op
else:
prepare = self.prepare_builtin_call
try:
@@ -1353,17 +1351,6 @@
assert False, 'unsupported oopspec: %s' % oopspec_name
return self._handle_oopspec_call(op, args, oopspecindex, extraeffect)
- # ----------
- # vector ops
-
- def _handle_vector_op(self, op, oopspec_name, args):
- if oopspec_name in ['vector_float_read',
- 'vector_float_write',
- 'vector_float_add']:
- return SpaceOperation(oopspec_name, op.args, op.result)
- else:
- raise NotSupported(oopspec_name)
-
def rewrite_op_jit_force_virtual(self, op):
return self._do_builtin_call(op)
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
@@ -947,7 +947,3 @@
assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_ARRAYCOPY
assert op1.args[2] == ListOfKind('int', [v3, v4, v5])
assert op1.args[3] == ListOfKind('ref', [v1, v2])
-
-def test_vector_ops():
- TP = lltype.Array(lltype.Float, hints={'nolength': True})
-
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -15,7 +15,6 @@
INT = 'i'
REF = 'r'
FLOAT = 'f'
-VECTOR = 'F'
HOLE = '_'
VOID = 'v'
@@ -512,9 +511,6 @@
def forget_value(self):
raise NotImplementedError
-class BoxVector(Box):
- _attrs_ = ()
-
class BoxInt(Box):
type = INT
_attrs_ = ('value',)
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -5718,6 +5718,9 @@
# not obvious, because of the exception UnicodeDecodeError that
# can be raised by ll_str2unicode()
+
+
+
##class TestOOtype(OptimizeOptTest, OOtypeMixin):
## def test_instanceof(self):
diff --git a/pypy/rlib/rvector.py b/pypy/rlib/rvector.py
deleted file mode 100644
--- a/pypy/rlib/rvector.py
+++ /dev/null
@@ -1,31 +0,0 @@
-
-from pypy.rpython.extregistry import ExtRegistryEntry
-
-class VectorContainer(object):
- """ Class that is a container for multiple float/int objects.
- Can be represented at jit-level by a single register, like xmm
- on x86 architecture
- """
-
-class FloatVectorContainer(VectorContainer):
- """ A container for float values
- """
- def __init__(self, val1, val2):
- self.v1 = val1
- self.v2 = val2
-
- def __repr__(self):
- return '' % (self.v1, self.v2)
-
-def vector_float_read(arr, index):
- return FloatVectorContainer(arr[index], arr[index + 1])
-vector_float_read.oopspec = 'vector_float_read(arr, index)'
-
-def vector_float_write(arr, index, container):
- arr[index] = container.v1
- arr[index + 1] = container.v2
-vector_float_write.oopspec = 'vector_from_write(arr, index, container)'
-
-def vector_float_add(left, right):
- return FloatVectorContainer(left.v1 + right.v1, left.v2 + right.v2)
-vector_float_add.oopspec = 'vector_float_add(left, right)'
diff --git a/pypy/rlib/test/test_rvector.py b/pypy/rlib/test/test_rvector.py
deleted file mode 100644
--- a/pypy/rlib/test/test_rvector.py
+++ /dev/null
@@ -1,56 +0,0 @@
-
-from pypy.rlib.rvector import (vector_float_read, vector_float_write,
- vector_float_add)
-from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.test.test_llinterp import interpret
-
-TP = lltype.Array(lltype.Float, hints={'nolength': True})
-
-class TestRVector(object):
- def test_direct_add(self):
- a = lltype.malloc(TP, 16, flavor='raw')
- b = lltype.malloc(TP, 16, flavor='raw')
- res = lltype.malloc(TP, 16, flavor='raw')
- a[0] = 1.2
- a[1] = 1.3
- b[0] = 0.1
- b[1] = 0.3
- a[10] = 8.3
- a[11] = 8.1
- b[10] = 7.8
- b[11] = 7.6
- f1 = vector_float_read(a, 0)
- f2 = vector_float_read(b, 0)
- vector_float_write(res, 2, vector_float_add(f1, f2))
- assert res[2] == 1.2 + 0.1
- assert res[3] == 1.3 + 0.3
- f1 = vector_float_read(a, 10)
- f2 = vector_float_read(b, 10)
- vector_float_write(res, 8, vector_float_add(f1, f2))
- assert res[8] == 8.3 + 7.8
- assert res[9] == 8.1 + 7.6
- lltype.free(a, flavor='raw')
- lltype.free(b, flavor='raw')
- lltype.free(res, flavor='raw')
-
- def test_interpret(self):
- def f():
- a = lltype.malloc(TP, 16, flavor='raw')
- b = lltype.malloc(TP, 16, flavor='raw')
- res = lltype.malloc(TP, 16, flavor='raw')
- try:
- a[0] = 1.2
- a[1] = 1.3
- b[0] = 0.1
- b[1] = 0.3
- f1 = vector_float_read(a, 0)
- f2 = vector_float_read(b, 0)
- vector_float_write(res, 8, vector_float_add(f1, f2))
- return res[8] * 100 + res[9]
- finally:
- lltype.free(a, flavor='raw')
- lltype.free(b, flavor='raw')
- lltype.free(res, flavor='raw')
-
- res = interpret(f, [])
- assert res == f()
From commits-noreply at bitbucket.org Wed May 4 13:15:56 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 13:15:56 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: remove more references to sse_float_add
Message-ID: <20110504111556.7EA3A2A202B@codespeak.net>
Author: Maciej Fijalkowski
Branch: numpy-exp
Changeset: r43880:40a28da2a896
Date: 2011-05-04 13:15 +0200
http://bitbucket.org/pypy/pypy/changeset/40a28da2a896/
Log: remove more references to sse_float_add
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -1202,17 +1202,6 @@
self.mc.XOR_rr(edx.value, edx.value)
self.mc.DIV_r(ecx.value)
- def genop_discard_sse_float_add(self, op, arglocs):
- base_loc, ofs_loc, itemsize, ofs, loc1, loc2 = arglocs
- assert isinstance(loc1, RegLoc)
- assert isinstance(loc2, RegLoc)
- assert isinstance(ofs, ImmedLoc)
- assert isinstance(itemsize, ImmedLoc)
- scale = _get_scale(itemsize.value)
- dest_addr = addr_add(base_loc, ofs_loc, ofs.value, scale)
- self.mc.ADDPD(loc1, loc2)
- self.mc.MOVAPD(dest_addr, loc1)
-
genop_llong_add = _binaryop("PADDQ", True)
genop_llong_sub = _binaryop("PSUBQ")
genop_llong_and = _binaryop("PAND", True)
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -1093,26 +1093,6 @@
imm(itemsize), imm(ofs),
xmmreg)
- def consider_sse_float_add(self, op):
- box1 = TempBox()
- box2 = TempBox()
- loc1 = self.xrm.force_allocate_reg(box1)
- loc2 = self.xrm.force_allocate_reg(box2, [box1])
- arraydescr = op.getdescr()
- ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(3))
- self._read_elem_into_xmmreg(loc1, op.getarg(0), op.getarg(3), ofs_loc,
- arraydescr)
- if op.getarg(1) != op.getarg(0):
- self._read_elem_into_xmmreg(loc2, op.getarg(1), op.getarg(3),
- ofs_loc, arraydescr)
- base_loc = self.rm.make_sure_var_in_reg(op.getarg(2), [op.getarg(3)])
- itemsize, ofs, _, _, _ = self._unpack_arraydescr(arraydescr)
- self.possibly_free_vars(op.getarglist())
- self.xrm.possibly_free_var(box1)
- self.xrm.possibly_free_var(box2)
- self.PerformDiscard(op, [base_loc, ofs_loc, imm(itemsize), imm(ofs),
- loc1, loc2])
-
consider_getarrayitem_raw = consider_getarrayitem_gc
consider_getarrayitem_gc_pure = consider_getarrayitem_gc
diff --git a/pypy/translator/c/src/float.h b/pypy/translator/c/src/float.h
--- a/pypy/translator/c/src/float.h
+++ b/pypy/translator/c/src/float.h
@@ -44,6 +44,3 @@
#define OP_CAST_FLOAT_TO_ULONGLONG(x,r) r = (unsigned long long)(x)
#endif
-/*** those operations don't do anything because they're in
- if we_are_jitted() path ***/
-#define OP_SSE_FLOAT_ADD(a, b, c, d, e)
From commits-noreply at bitbucket.org Wed May 4 14:02:55 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Wed, 4 May 2011 14:02:55 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: - More tests.
Message-ID: <20110504120255.69ADD2A202B@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43881:b971a76ce381
Date: 2011-05-04 13:15 +0200
http://bitbucket.org/pypy/pypy/changeset/b971a76ce381/
Log: - More tests.
- Adapt pypyjit to turn on CodeWriter.debug, producing files in
usession-*/jitcodes/.
diff --git a/pypy/jit/codewriter/codewriter.py b/pypy/jit/codewriter/codewriter.py
--- a/pypy/jit/codewriter/codewriter.py
+++ b/pypy/jit/codewriter/codewriter.py
@@ -13,8 +13,9 @@
class CodeWriter(object):
callcontrol = None # for tests
+ debug = False
- def __init__(self, cpu=None, jitdrivers_sd=[], debug=False):
+ def __init__(self, cpu=None, jitdrivers_sd=[]):
self.cpu = cpu
self.assembler = Assembler()
self.callcontrol = CallControl(cpu, jitdrivers_sd)
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
@@ -66,7 +66,8 @@
#
res = self.meta_interp(f, [100, 7])
assert res == 700
- self.check_loops(getfield_gc=0, everywhere=True)
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0,
+ everywhere=True)
#
from pypy.jit.metainterp.warmspot import get_stats
loops = get_stats().loops
@@ -95,13 +96,40 @@
assert f(100, 7) == 721
res = self.meta_interp(f, [100, 7])
assert res == 721
- self.check_loops(getfield_gc=1)
+ self.check_loops(guard_not_invalidated=0, getfield_gc=1)
#
from pypy.jit.metainterp.warmspot import get_stats
loops = get_stats().loops
for loop in loops:
assert loop.quasi_immutable_deps is None
+ def test_opt_via_virtual_1(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ class A:
+ pass
+ def f(a, x):
+ foo = Foo(a)
+ total = 0
+ while x > 0:
+ myjitdriver.jit_merge_point(foo=foo, x=x, total=total)
+ # make it a Constant after optimization only
+ a = A()
+ a.foo = foo
+ foo = a.foo
+ # read a quasi-immutable field out of it
+ total += foo.a
+ x -= 1
+ return total
+ #
+ res = self.meta_interp(f, [100, 7])
+ assert res == 700
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0,
+ everywhere=True)
+
def test_change_during_tracing_1(self):
myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
class Foo:
@@ -125,7 +153,7 @@
assert f(100, 7) == 721
res = self.meta_interp(f, [100, 7])
assert res == 721
- self.check_loops(getfield_gc=1)
+ self.check_loops(guard_not_invalidated=0, getfield_gc=1)
def test_change_during_tracing_2(self):
myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -151,7 +179,7 @@
assert f(100, 7) == 700
res = self.meta_interp(f, [100, 7])
assert res == 700
- self.check_loops(getfield_gc=1)
+ self.check_loops(guard_not_invalidated=0, getfield_gc=1)
def test_change_invalidate_reentering(self):
myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -177,7 +205,7 @@
assert g(100, 7) == 700707
res = self.meta_interp(g, [100, 7])
assert res == 700707
- self.check_loops(getfield_gc=0)
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0)
def test_invalidate_while_running(self):
jitdriver = JitDriver(greens=['foo'], reds=['i', 'total'])
@@ -312,8 +340,47 @@
#
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)
+ self.check_loops(guard_not_invalidated=2, 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_length_1(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['lst?[*]']
+ def __init__(self, lst):
+ self.lst = lst
+ class A:
+ pass
+ 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)
+ # make it a Constant after optimization only
+ a = A()
+ a.foo = foo
+ foo = a.foo
+ # read a quasi-immutable field out of it
+ total += foo.lst[1]
+ # also read the length
+ total += len(foo.lst)
+ x -= 1
+ return total
+ #
+ res = self.meta_interp(f, [100, 7])
+ assert res == 714
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0,
+ getarrayitem_gc=0, getarrayitem_gc_pure=0,
+ arraylen_gc=0, everywhere=True)
#
from pypy.jit.metainterp.warmspot import get_stats
loops = get_stats().loops
diff --git a/pypy/jit/tl/pypyjit.py b/pypy/jit/tl/pypyjit.py
--- a/pypy/jit/tl/pypyjit.py
+++ b/pypy/jit/tl/pypyjit.py
@@ -56,6 +56,10 @@
assert False
print config
+from pypy.jit.codewriter.codewriter import CodeWriter
+CodeWriter.debug = True
+
+
import sys, pdb
space = Space(config)
From commits-noreply at bitbucket.org Wed May 4 14:02:56 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Wed, 4 May 2011 14:02:56 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Oups.
Message-ID: <20110504120256.E57822A202B@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43882:0f46516f8a80
Date: 2011-05-04 13:27 +0200
http://bitbucket.org/pypy/pypy/changeset/0f46516f8a80/
Log: Oups.
diff --git a/pypy/jit/codewriter/codewriter.py b/pypy/jit/codewriter/codewriter.py
--- a/pypy/jit/codewriter/codewriter.py
+++ b/pypy/jit/codewriter/codewriter.py
@@ -20,7 +20,6 @@
self.assembler = Assembler()
self.callcontrol = CallControl(cpu, jitdrivers_sd)
self._seen_files = set()
- self.debug = debug
def transform_func_to_jitcode(self, func, values, type_system='lltype'):
"""For testing."""
From commits-noreply at bitbucket.org Wed May 4 14:02:59 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Wed, 4 May 2011 14:02:59 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: !@$%^&@#!
Message-ID: <20110504120259.BBA622A2034@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43883:155f4f553dbe
Date: 2011-05-04 13:59 +0200
http://bitbucket.org/pypy/pypy/changeset/155f4f553dbe/
Log: !@$%^&@#!
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -31,7 +31,7 @@
_immutable_fields_ = ['code?',
'w_func_globals?',
'closure?',
- 'defs?[*]']
+ 'defs_w?[*]']
def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
forcename=None):
From commits-noreply at bitbucket.org Wed May 4 14:03:01 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Wed, 4 May 2011 14:03:01 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Another passing test
Message-ID: <20110504120301.D4FA42A2032@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43884:ac7ddb599873
Date: 2011-05-04 13:59 +0200
http://bitbucket.org/pypy/pypy/changeset/ac7ddb599873/
Log: Another passing test
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
@@ -388,6 +388,39 @@
assert len(loop.quasi_immutable_deps) == 1
assert isinstance(loop.quasi_immutable_deps.keys()[0], QuasiImmut)
+ def test_list_pass_around(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['lst?[*]']
+ def __init__(self, lst):
+ self.lst = lst
+ def g(lst):
+ return lst[1]
+ def f(a, x):
+ lst1 = [0, 0]
+ g(lst1)
+ 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 += g(foo.lst)
+ x -= 1
+ return total
+ #
+ res = self.meta_interp(f, [100, 7])
+ assert res == 700
+ self.check_loops(guard_not_invalidated=2, 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:
From commits-noreply at bitbucket.org Wed May 4 14:03:03 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Wed, 4 May 2011 14:03:03 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Updates to pypyjit.
Message-ID: <20110504120303.BE3A52A2031@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43885:922c4d33b318
Date: 2011-05-04 12:01 +0000
http://bitbucket.org/pypy/pypy/changeset/922c4d33b318/
Log: Updates to pypyjit.
diff --git a/pypy/jit/tl/pypyjit.py b/pypy/jit/tl/pypyjit.py
--- a/pypy/jit/tl/pypyjit.py
+++ b/pypy/jit/tl/pypyjit.py
@@ -56,10 +56,6 @@
assert False
print config
-from pypy.jit.codewriter.codewriter import CodeWriter
-CodeWriter.debug = True
-
-
import sys, pdb
space = Space(config)
@@ -119,6 +115,8 @@
# print a message, and restart
unixcheckpoint.restartable_point(auto='run')
+ from pypy.jit.codewriter.codewriter import CodeWriter
+ CodeWriter.debug = True
from pypy.jit.tl.pypyjit_child import run_child, run_child_ootype
if BACKEND == 'c':
run_child(globals(), locals())
diff --git a/pypy/jit/tl/pypyjit_demo.py b/pypy/jit/tl/pypyjit_demo.py
--- a/pypy/jit/tl/pypyjit_demo.py
+++ b/pypy/jit/tl/pypyjit_demo.py
@@ -1,18 +1,11 @@
try:
- def g(x):
- return x - 1
def f(x):
- while x:
- x = g(x)
- import cProfile
- import time
- t1 = time.time()
- cProfile.run("f(10000000)")
- t2 = time.time()
- f(10000000)
- t3 = time.time()
- print t2 - t1, t3 - t2, (t3 - t2) / (t2 - t1)
+ i = 0
+ while i < x:
+ range(i)
+ i += 1
+ f(10000)
except Exception, e:
print "Exception: ", type(e)
print e
From commits-noreply at bitbucket.org Wed May 4 14:03:05 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Wed, 4 May 2011 14:03:05 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Updates to test_pypy_c_new.
Message-ID: <20110504120305.9CC192A2037@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43886:ae051034f9f5
Date: 2011-05-04 12:01 +0000
http://bitbucket.org/pypy/pypy/changeset/ae051034f9f5/
Log: Updates to test_pypy_c_new.
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -239,7 +239,7 @@
i19 = int_add_ovf(i10, i17)
guard_no_overflow(descr=)
--TICK--
- jump(p0, p1, p2, p3, p4, p5, i19, p7, i17, i9, i10, p11, p12, p13, p14, descr=)
+ jump(p0, p1, p2, p3, p4, p5, i19, p7, i17, i9, i10, p11, p12, p13, descr=)
""")
def test_static_classmethod_call(self):
@@ -272,7 +272,7 @@
i18 = force_token()
i20 = int_sub(i17, 1)
--TICK--
- jump(p0, p1, p2, p3, p4, p5, i20, p7, i17, i9, p10, p11, p12, p13, descr=)
+ jump(p0, p1, p2, p3, p4, p5, i20, p7, i17, i9, p10, p11, p12, descr=)
""")
def test_default_and_kw(self):
@@ -1665,3 +1665,7 @@
assert log.result == 300
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id('shift', "") # optimized away
+
+
+def test_count():
+ assert 0, "loops too long! revert d5dd9462363a on model.py"
From commits-noreply at bitbucket.org Wed May 4 14:52:19 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 14:52:19 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: some simple benchmarks
Message-ID: <20110504125219.9E1E62A202B@codespeak.net>
Author: Maciej Fijalkowski
Branch: numpy-exp
Changeset: r43887:8550f8c9b924
Date: 2011-05-04 14:51 +0200
http://bitbucket.org/pypy/pypy/changeset/8550f8c9b924/
Log: some simple benchmarks
diff --git a/pypy/module/micronumpy/bench/add.py b/pypy/module/micronumpy/bench/add.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/bench/add.py
@@ -0,0 +1,10 @@
+
+import numpy
+
+def f():
+ a = numpy.zeros(1000000)
+ a = a + a + a + a + a
+ if hasattr(a, 'force'):
+ a.force()
+
+f()
diff --git a/pypy/module/micronumpy/bench/iterate.py b/pypy/module/micronumpy/bench/iterate.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/bench/iterate.py
@@ -0,0 +1,9 @@
+
+def f():
+ sum = 0
+ a = numpy.zeros(1000000)
+ for i in range(1000000):
+ sum += a[i]
+ return sum
+
+f()
From commits-noreply at bitbucket.org Wed May 4 14:53:31 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 14:53:31 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: increase numbers
Message-ID: <20110504125331.DD6992A202B@codespeak.net>
Author: Maciej Fijalkowski
Branch: numpy-exp
Changeset: r43888:3a9d77b789e1
Date: 2011-05-04 14:53 +0200
http://bitbucket.org/pypy/pypy/changeset/3a9d77b789e1/
Log: increase numbers
diff --git a/pypy/module/micronumpy/bench/add.py b/pypy/module/micronumpy/bench/add.py
--- a/pypy/module/micronumpy/bench/add.py
+++ b/pypy/module/micronumpy/bench/add.py
@@ -2,7 +2,7 @@
import numpy
def f():
- a = numpy.zeros(1000000)
+ a = numpy.zeros(10000000)
a = a + a + a + a + a
if hasattr(a, 'force'):
a.force()
diff --git a/pypy/module/micronumpy/bench/iterate.py b/pypy/module/micronumpy/bench/iterate.py
--- a/pypy/module/micronumpy/bench/iterate.py
+++ b/pypy/module/micronumpy/bench/iterate.py
@@ -1,8 +1,10 @@
+
+import numpy
def f():
sum = 0
- a = numpy.zeros(1000000)
- for i in range(1000000):
+ a = numpy.zeros(10000000)
+ for i in range(10000000):
sum += a[i]
return sum
From commits-noreply at bitbucket.org Wed May 4 15:34:38 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 15:34:38 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: Draft a blog post
Message-ID: <20110504133438.9D4532A202B@codespeak.net>
Author: Maciej Fijalkowski
Branch: extradoc
Changeset: r3553:6fdbe2ef669a
Date: 2011-05-04 15:34 +0200
http://bitbucket.org/pypy/extradoc/changeset/6fdbe2ef669a/
Log: Draft a blog post
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
new file mode 100644
--- /dev/null
+++ b/blog/draft/numpy_roadmap.rst
@@ -0,0 +1,74 @@
+
+Numpy in PyPy - status and roadmap
+==================================
+
+Hello
+
+When it comes to PyPy's requested features, there are few features that were
+requested over and over again. In the random order:
+
+* JIT and stackless integration (discussed at the recent sprint)
+
+* 2.7 compatibility (done!)
+
+* numpy integration
+
+Among those things, only numpy integration hasn't been at least a bit tackled
+and this post discusses what's the current status and what's the possible plan.
+
+**The short version for impatient: there are experiments being done, which are
+already faster and better than numpy, and there
+is a path forward, but there is a definite lack of dedicated people or money
+to tackle that.**
+
+The longer version
+------------------
+
+The numpy effort in PyPy was my project for a while on an on-and-off (mostly
+off) basis over the past two years. There were `some experiments`_ then
+mostly nothing and then some more experiments that are documented below.
+
+The general idea that seems to be worthwhile pursuing would be to implement
+numpy in RPython (an implementation language of PyPy) and then leverage
+JIT to achieve extra speedups. The really cool thing about this part is that
+overall JIT improvements will benefit numpy performance out of the box, without
+the extra tweaking. As of now there is branch called `numpy-exp`_ which contains
+a translatable version of a very minimal version of numpy in the module
+called micronumpy. `Example benchmarks`_ show the following:
+
++--------------------------------+---------------+-------------+
+| | add | iterate |
++--------------------------------+---------------+-------------+
+| CPython 2.6.5 with numpy 1.3.0 | 0.260s (1x) | 4.2 (1x) |
++--------------------------------+---------------+-------------+
+| PyPy numpy-exp @ 3a9d77b789e1 | 0.120s (2.2x) | 0.087 (48x) |
++--------------------------------+---------------+-------------+
+
+As you can see, the moment floats cross the numpy-python boundary, PyPy's
+JIT goes blazingly fast, but even running array addition is faster by
+a fair degree (although numexpr is still faster, we're working on it).
+
+The exact way how array addition is implemented is worth another blog post,
+but in short it lazily evaluates the expression forcing it at the end
+and avoiding intermediate results. This way scales much better than numexpr
+and can lead to speeding up all the operations that you can perform on matrices.
+
+The next obvious step would be to extend the JIT to use SSE operations on
+intel x86 architecture which should speed it up by about additional 2x.
+
+Overall it seems pretty obvious that reimplementing numpy in PyPy (in RPython)
+can bring most of the useful compatibility within a month-two-three of work.
+It also seems that the result will be faster for most cases and the same speed
+as original numpy for other cases. The only problem is finding the dedicated
+person willing to spend quite some time on that and personally I would be
+willing to both mentor such a person and encourage him or her :)
+
+Another option would be to sponsor numpy development. In case you're interested,
+please get in touch with us or leave your email in comments.
+
+Cheers,
+fijal
+
+.. _`some experiments`: http://morepypy.blogspot.com/2009/07/pypy-numeric-experiments.html
+.. _`numpy-exp`: https://bitbucket.org/pypy/pypy/src/numpy-exp/
+.. _`Example benchmarks`: https://bitbucket.org/pypy/pypy/src/numpy-exp/pypy/module/micronumpy/bench
From commits-noreply at bitbucket.org Wed May 4 15:40:44 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 15:40:44 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: strike irrelevant bits
Message-ID: <20110504134044.3BA2C2A202B@codespeak.net>
Author: Maciej Fijalkowski
Branch: extradoc
Changeset: r3554:8a6498c5cb18
Date: 2011-05-04 15:40 +0200
http://bitbucket.org/pypy/extradoc/changeset/8a6498c5cb18/
Log: strike irrelevant bits
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -4,17 +4,9 @@
Hello
-When it comes to PyPy's requested features, there are few features that were
-requested over and over again. In the random order:
-
-* JIT and stackless integration (discussed at the recent sprint)
-
-* 2.7 compatibility (done!)
-
-* numpy integration
-
-Among those things, only numpy integration hasn't been at least a bit tackled
-and this post discusses what's the current status and what's the possible plan.
+Among things people really want to have in PyPy is numpy integration.
+This post tries to describe where we are, what we plan (or what we don't plan)
+and how you can help.
**The short version for impatient: there are experiments being done, which are
already faster and better than numpy, and there
From commits-noreply at bitbucket.org Wed May 4 15:50:30 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Wed, 4 May 2011 15:50:30 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: First pass grammar/english changes.
Message-ID: <20110504135030.E80FD36C207@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3555:46deb3fc5687
Date: 2011-05-04 09:50 -0400
http://bitbucket.org/pypy/extradoc/changeset/46deb3fc5687/
Log: First pass grammar/english changes.
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -2,31 +2,31 @@
Numpy in PyPy - status and roadmap
==================================
-Hello
+Hello.
-Among things people really want to have in PyPy is numpy integration.
-This post tries to describe where we are, what we plan (or what we don't plan)
-and how you can help.
+
+NumPy integration is one of the single most requested features for PyPy. This
+post tries to describe where we are, what we plan (or what we don't plan), and
+how you can help.
**The short version for impatient: there are experiments being done, which are
-already faster and better than numpy, and there
-is a path forward, but there is a definite lack of dedicated people or money
-to tackle that.**
+already faster and better than numpy, and there is a path forward, but there is
+a definite lack of dedicated people or money to tackle that.**
The longer version
------------------
-The numpy effort in PyPy was my project for a while on an on-and-off (mostly
-off) basis over the past two years. There were `some experiments`_ then
-mostly nothing and then some more experiments that are documented below.
+The NumPy effort in PyPy has, for the past two years, been my on-and-off-again
+project. There were `some experiments`_ then mostly nothing and then some more
+experiments that are documented below.
-The general idea that seems to be worthwhile pursuing would be to implement
-numpy in RPython (an implementation language of PyPy) and then leverage
-JIT to achieve extra speedups. The really cool thing about this part is that
-overall JIT improvements will benefit numpy performance out of the box, without
-the extra tweaking. As of now there is branch called `numpy-exp`_ which contains
-a translatable version of a very minimal version of numpy in the module
-called micronumpy. `Example benchmarks`_ show the following:
+The general idea that seems to be worth pursuing would be to implement NumPy in
+RPython (the implementation language of PyPy) and then leverage JIT to achieve
+extra speedups. The really cool thing about this part is that overall JIT
+improvements will benefit NumPy performance out of the box, without extra
+tweaking. As of now there is branch called `numpy-exp`_ which contains a
+translatable version of a very minimal version of numpy in the module called
+``micronumpy``. `Example benchmarks`_ show the following:
+--------------------------------+---------------+-------------+
| | add | iterate |
@@ -36,27 +36,27 @@
| PyPy numpy-exp @ 3a9d77b789e1 | 0.120s (2.2x) | 0.087 (48x) |
+--------------------------------+---------------+-------------+
-As you can see, the moment floats cross the numpy-python boundary, PyPy's
-JIT goes blazingly fast, but even running array addition is faster by
-a fair degree (although numexpr is still faster, we're working on it).
+As you can see, the moment floats cross the numpy-python boundary, PyPy's JIT
+goes blazingly fast, but even running array addition is faster by a fair degree
+(although numexpr is still faster, we're working on it).
-The exact way how array addition is implemented is worth another blog post,
-but in short it lazily evaluates the expression forcing it at the end
-and avoiding intermediate results. This way scales much better than numexpr
-and can lead to speeding up all the operations that you can perform on matrices.
+The exact way how array addition is implemented is worth another blog post, but
+in short it lazily evaluates the expression forcing it at the end and avoiding
+intermediate results. This way scales much better than numexpr and can lead to
+speeding up all the operations that you can perform on matrices.
-The next obvious step would be to extend the JIT to use SSE operations on
-intel x86 architecture which should speed it up by about additional 2x.
+The next obvious step would be to extend the JIT to use SSE operations on x86
+CPUs, which should speed it up by about additional 2x.
-Overall it seems pretty obvious that reimplementing numpy in PyPy (in RPython)
+Overall it seems pretty obvious that reimplementing NumPy in PyPy (in RPython)
can bring most of the useful compatibility within a month-two-three of work.
It also seems that the result will be faster for most cases and the same speed
as original numpy for other cases. The only problem is finding the dedicated
-person willing to spend quite some time on that and personally I would be
-willing to both mentor such a person and encourage him or her :)
+persons willing to spend quite some time on this and however, I am willing to
+both mentor such a person and encourage him or her.
-Another option would be to sponsor numpy development. In case you're interested,
-please get in touch with us or leave your email in comments.
+Another option would be to sponsor NumPy development. In case you're
+interested, please get in touch with us or leave your email in comments.
Cheers,
fijal
From commits-noreply at bitbucket.org Wed May 4 15:56:48 2011
From: commits-noreply at bitbucket.org (lac)
Date: Wed, 4 May 2011 15:56:48 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: fix one missing article
Message-ID: <20110504135648.D5F1B2A202B@codespeak.net>
Author: Laura Creighton
Branch: extradoc
Changeset: r3556:cc2a7213531a
Date: 2011-05-04 15:56 +0200
http://bitbucket.org/pypy/extradoc/changeset/cc2a7213531a/
Log: fix one missing article
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -21,7 +21,7 @@
experiments that are documented below.
The general idea that seems to be worth pursuing would be to implement NumPy in
-RPython (the implementation language of PyPy) and then leverage JIT to achieve
+RPython (the implementation language of PyPy) and then leverage the JIT to achieve
extra speedups. The really cool thing about this part is that overall JIT
improvements will benefit NumPy performance out of the box, without extra
tweaking. As of now there is branch called `numpy-exp`_ which contains a
diff --git a/sprintinfo/gothenburg-2011/people.txt b/sprintinfo/gothenburg-2011/people.txt
--- a/sprintinfo/gothenburg-2011/people.txt
+++ b/sprintinfo/gothenburg-2011/people.txt
@@ -11,7 +11,7 @@
Jacob Hallen lives there no peppers
Laura Creighton lives there
Anders Hammarquist lives there
-Carl Friedrich Bolz 24-30 J+L's house Vegan
+Carl Friedrich Bolz 24-1 J+L's house Vegan
Lukas Diekmann 24-2 J+L's house
David Schneider 26-01 SGS Veckobostader
Antonio Cuni 26-30 Hotel Poseidon his own diet :)
From commits-noreply at bitbucket.org Wed May 4 15:59:52 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Wed, 4 May 2011 15:59:52 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: link numepxr
Message-ID: <20110504135952.D63652A202B@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3557:234020284cc0
Date: 2011-05-04 09:59 -0400
http://bitbucket.org/pypy/extradoc/changeset/234020284cc0/
Log: link numepxr
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -38,7 +38,7 @@
As you can see, the moment floats cross the numpy-python boundary, PyPy's JIT
goes blazingly fast, but even running array addition is faster by a fair degree
-(although numexpr is still faster, we're working on it).
+(although `numexpr`_ is still faster, we're working on it).
The exact way how array addition is implemented is worth another blog post, but
in short it lazily evaluates the expression forcing it at the end and avoiding
@@ -64,3 +64,4 @@
.. _`some experiments`: http://morepypy.blogspot.com/2009/07/pypy-numeric-experiments.html
.. _`numpy-exp`: https://bitbucket.org/pypy/pypy/src/numpy-exp/
.. _`Example benchmarks`: https://bitbucket.org/pypy/pypy/src/numpy-exp/pypy/module/micronumpy/bench
+.. _`numexpr`: http://code.google.com/p/numexpr/
\ No newline at end of file
From commits-noreply at bitbucket.org Wed May 4 16:12:10 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Wed, 4 May 2011 16:12:10 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: heavy refactor of the draft
Message-ID: <20110504141210.AFADD2A202B@codespeak.net>
Author: Antonio Cuni
Branch: extradoc
Changeset: r3558:01cbc62f1a4f
Date: 2011-05-04 16:09 +0200
http://bitbucket.org/pypy/extradoc/changeset/01cbc62f1a4f/
Log: heavy refactor of the draft
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -4,30 +4,34 @@
Hello.
-
NumPy integration is one of the single most requested features for PyPy. This
post tries to describe where we are, what we plan (or what we don't plan), and
how you can help.
-**The short version for impatient: there are experiments being done, which are
-already faster and better than numpy, and there is a path forward, but there is
-a definite lack of dedicated people or money to tackle that.**
+**Short version for the impatient: we are doing experiments, which show that
+PyPy+numpy can be faster and better than CPython+numpy. We have a plan on how
+to do it, but at the moment there is lack of dedicated people or money to tackle
+that.**
The longer version
------------------
-The NumPy effort in PyPy has, for the past two years, been my on-and-off-again
-project. There were `some experiments`_ then mostly nothing and then some more
-experiments that are documented below.
+Integrating numpy in PyPy has been my pet project on an on-and-off (mostly
+off) basis over the past two years. There were `some experiments`_, then
+a long pause, and then some more experiments which are documented below.
-The general idea that seems to be worth pursuing would be to implement NumPy in
-RPython (the implementation language of PyPy) and then leverage JIT to achieve
-extra speedups. The really cool thing about this part is that overall JIT
-improvements will benefit NumPy performance out of the box, without extra
-tweaking. As of now there is branch called `numpy-exp`_ which contains a
+The general idea is **not** to use the existing CPython module, but to
+reimplement numpy in RPython (i.e., the language PyPy is implemented in), thus
+letting our JIT achieve extra speedups. The really cool thing about this part
+is that numpy will automatically benefit of any general JIT improvements,
+without any need of extra tweaking.
+
+At the moment, there is branch called `numpy-exp`_ which contains a
translatable version of a very minimal version of numpy in the module called
``micronumpy``. `Example benchmarks`_ show the following:
+XXX: you should briefly describe what the benchmarks do
+
+--------------------------------+---------------+-------------+
| | add | iterate |
+--------------------------------+---------------+-------------+
@@ -36,20 +40,30 @@
| PyPy numpy-exp @ 3a9d77b789e1 | 0.120s (2.2x) | 0.087 (48x) |
+--------------------------------+---------------+-------------+
-As you can see, the moment floats cross the numpy-python boundary, PyPy's JIT
-goes blazingly fast, but even running array addition is faster by a fair degree
-(although numexpr is still faster, we're working on it).
+The ``add`` benchmark spends most of the time inside the ``+`` operator
+between arrays, which in CPython is implemented in C. As you can see from the
+table above, the PyPy version is ~2 times faster. (Although numexpr_ is still
+faster than PyPy, but we're working on it).
The exact way how array addition is implemented is worth another blog post, but
in short it lazily evaluates the expression forcing it at the end and avoiding
intermediate results. This way scales much better than numexpr and can lead to
speeding up all the operations that you can perform on matrices.
-The next obvious step would be to extend the JIT to use SSE operations on x86
-CPUs, which should speed it up by about additional 2x.
+``iterate`` is even more interesting, because it spends most of the time
+inside a Python loop: the PyPy version is ~48 times faster, because the JIT
+can optimize across the python/numpy boundary, showing the potential of this
+approach.
-Overall it seems pretty obvious that reimplementing NumPy in PyPy (in RPython)
-can bring most of the useful compatibility within a month-two-three of work.
+The next obvious step to get even more speedups would be to extend the JIT to
+use SSE operations on x86 CPUs, which should speed it up by about additional
+2x.
+
+The drawback of this approach is that we need to reimplement numpy in RPython,
+which takes time. A very rough estimate is that it would be possible to
+implement an useful subset of it (for some definition of useful) in a period
+of time comprised between one and three man-months.
+
It also seems that the result will be faster for most cases and the same speed
as original numpy for other cases. The only problem is finding the dedicated
persons willing to spend quite some time on this and however, I am willing to
From commits-noreply at bitbucket.org Wed May 4 16:12:12 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Wed, 4 May 2011 16:12:12 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: merge heads
Message-ID: <20110504141212.BA2182A202F@codespeak.net>
Author: Antonio Cuni
Branch: extradoc
Changeset: r3559:012db186bc0a
Date: 2011-05-04 16:11 +0200
http://bitbucket.org/pypy/extradoc/changeset/012db186bc0a/
Log: merge heads
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -78,3 +78,4 @@
.. _`some experiments`: http://morepypy.blogspot.com/2009/07/pypy-numeric-experiments.html
.. _`numpy-exp`: https://bitbucket.org/pypy/pypy/src/numpy-exp/
.. _`Example benchmarks`: https://bitbucket.org/pypy/pypy/src/numpy-exp/pypy/module/micronumpy/bench
+.. _`numexpr`: http://code.google.com/p/numexpr/
diff --git a/sprintinfo/gothenburg-2011/people.txt b/sprintinfo/gothenburg-2011/people.txt
--- a/sprintinfo/gothenburg-2011/people.txt
+++ b/sprintinfo/gothenburg-2011/people.txt
@@ -11,7 +11,7 @@
Jacob Hallen lives there no peppers
Laura Creighton lives there
Anders Hammarquist lives there
-Carl Friedrich Bolz 24-30 J+L's house Vegan
+Carl Friedrich Bolz 24-1 J+L's house Vegan
Lukas Diekmann 24-2 J+L's house
David Schneider 26-01 SGS Veckobostader
Antonio Cuni 26-30 Hotel Poseidon his own diet :)
From commits-noreply at bitbucket.org Wed May 4 16:18:29 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Wed, 4 May 2011 16:18:29 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: small changes.
Message-ID: <20110504141829.A8E2C2A202B@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3560:15ebcba5ff07
Date: 2011-05-04 10:18 -0400
http://bitbucket.org/pypy/extradoc/changeset/15ebcba5ff07/
Log: small changes.
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -10,18 +10,18 @@
**Short version for the impatient: we are doing experiments, which show that
PyPy+numpy can be faster and better than CPython+numpy. We have a plan on how
-to do it, but at the moment there is lack of dedicated people or money to tackle
-that.**
+to move forward, but at the moment there is lack of dedicated people or money
+to tackle it.**
The longer version
------------------
-Integrating numpy in PyPy has been my pet project on an on-and-off (mostly
-off) basis over the past two years. There were `some experiments`_, then
-a long pause, and then some more experiments which are documented below.
+Integrating numpy in PyPy has been my pet project on an on-and-off (mostly off)
+basis over the past two years. There were `some experiments`_, then a long
+pause, and then some more experiments which are documented below.
The general idea is **not** to use the existing CPython module, but to
-reimplement numpy in RPython (i.e., the language PyPy is implemented in), thus
+reimplement numpy in RPython (i.e. the language PyPy is implemented in), thus
letting our JIT achieve extra speedups. The really cool thing about this part
is that numpy will automatically benefit of any general JIT improvements,
without any need of extra tweaking.
@@ -53,7 +53,7 @@
``iterate`` is even more interesting, because it spends most of the time
inside a Python loop: the PyPy version is ~48 times faster, because the JIT
can optimize across the python/numpy boundary, showing the potential of this
-approach.
+approach, users are not penalized for writing their loops in Python.
The next obvious step to get even more speedups would be to extend the JIT to
use SSE operations on x86 CPUs, which should speed it up by about additional
From commits-noreply at bitbucket.org Wed May 4 16:26:20 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Wed, 4 May 2011 16:26:20 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: trailing slash,
makes all the difference.
Message-ID: <20110504142620.DCE2936C202@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3561:c6c8acc2febe
Date: 2011-05-04 10:26 -0400
http://bitbucket.org/pypy/extradoc/changeset/c6c8acc2febe/
Log: trailing slash, makes all the difference.
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -77,5 +77,5 @@
.. _`some experiments`: http://morepypy.blogspot.com/2009/07/pypy-numeric-experiments.html
.. _`numpy-exp`: https://bitbucket.org/pypy/pypy/src/numpy-exp/
-.. _`Example benchmarks`: https://bitbucket.org/pypy/pypy/src/numpy-exp/pypy/module/micronumpy/bench
+.. _`Example benchmarks`: https://bitbucket.org/pypy/pypy/src/numpy-exp/pypy/module/micronumpy/bench/
.. _`numexpr`: http://code.google.com/p/numexpr/
From commits-noreply at bitbucket.org Wed May 4 17:55:10 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 17:55:10 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: rewrite a bit
Message-ID: <20110504155510.418D12A202B@codespeak.net>
Author: Maciej Fijalkowski
Branch: extradoc
Changeset: r3562:d198c4ce4cec
Date: 2011-05-04 17:54 +0200
http://bitbucket.org/pypy/extradoc/changeset/d198c4ce4cec/
Log: rewrite a bit
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -30,8 +30,6 @@
translatable version of a very minimal version of numpy in the module called
``micronumpy``. `Example benchmarks`_ show the following:
-XXX: you should briefly describe what the benchmarks do
-
+--------------------------------+---------------+-------------+
| | add | iterate |
+--------------------------------+---------------+-------------+
@@ -41,23 +39,25 @@
+--------------------------------+---------------+-------------+
The ``add`` benchmark spends most of the time inside the ``+`` operator
-between arrays, which in CPython is implemented in C. As you can see from the
-table above, the PyPy version is ~2 times faster. (Although numexpr_ is still
-faster than PyPy, but we're working on it).
+between one array five times, which in CPython is implemented in C.
+As you can see from the table above, the PyPy version is already
+~2 times faster. (Although numexpr_ is still faster than PyPy,
+but we're working on it).
The exact way how array addition is implemented is worth another blog post, but
in short it lazily evaluates the expression forcing it at the end and avoiding
intermediate results. This way scales much better than numexpr and can lead to
speeding up all the operations that you can perform on matrices.
-``iterate`` is even more interesting, because it spends most of the time
+The next obvious step to get even more speedups would be to extend the JIT to
+use SSE operations on x86 CPUs, which should speed it up by about additional
+2x, as well as using multiple threads to do operations.
+
+``iterate`` is also interesting, but for entirely different reasons.
+On CPython it spends most of the time
inside a Python loop: the PyPy version is ~48 times faster, because the JIT
can optimize across the python/numpy boundary, showing the potential of this
-approach, users are not penalized for writing their loops in Python.
-
-The next obvious step to get even more speedups would be to extend the JIT to
-use SSE operations on x86 CPUs, which should speed it up by about additional
-2x.
+approach, users are not grossly penalized for writing their loops in Python.
The drawback of this approach is that we need to reimplement numpy in RPython,
which takes time. A very rough estimate is that it would be possible to
@@ -69,6 +69,12 @@
persons willing to spend quite some time on this and however, I am willing to
both mentor such a person and encourage him or her.
+The good starting point for helping would be to look at what's already
+implemented in micronumpy modules and try extending it. Adding a `-` operator
+or adding integers would be an interesting start. Drop by on #pypy on
+irc.freenode.net or get in contact with developers via some other channel
+if you want to help.
+
Another option would be to sponsor NumPy development. In case you're
interested, please get in touch with us or leave your email in comments.
From commits-noreply at bitbucket.org Wed May 4 17:59:23 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Wed, 4 May 2011 17:59:23 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: grammar, also an XXX
Message-ID: <20110504155923.C483E2A202B@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3563:52fa9ae788ab
Date: 2011-05-04 11:59 -0400
http://bitbucket.org/pypy/extradoc/changeset/52fa9ae788ab/
Log: grammar, also an XXX
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -38,26 +38,25 @@
| PyPy numpy-exp @ 3a9d77b789e1 | 0.120s (2.2x) | 0.087 (48x) |
+--------------------------------+---------------+-------------+
-The ``add`` benchmark spends most of the time inside the ``+`` operator
-between one array five times, which in CPython is implemented in C.
-As you can see from the table above, the PyPy version is already
-~2 times faster. (Although numexpr_ is still faster than PyPy,
-but we're working on it).
+The ``add`` benchmark spends most of the time inside the ``+`` operator on
+arrays (doing ``a + a + a + a + a``), , which in CPython is implemented in C.
+As you can see from the table above, the PyPy version is already ~2 times
+faster. (Although numexpr_ is still faster than PyPy, but we're working on it).
-The exact way how array addition is implemented is worth another blog post, but
-in short it lazily evaluates the expression forcing it at the end and avoiding
-intermediate results. This way scales much better than numexpr and can lead to
+The exact way array addition is implemented is worth another blog post, but in
+short it lazily evaluates the expression and computes it at the end, avoiding
+intermediate results. This way scales much better than numexpr (XXX numpy?) and can lead to
speeding up all the operations that you can perform on matrices.
The next obvious step to get even more speedups would be to extend the JIT to
use SSE operations on x86 CPUs, which should speed it up by about additional
2x, as well as using multiple threads to do operations.
-``iterate`` is also interesting, but for entirely different reasons.
-On CPython it spends most of the time
-inside a Python loop: the PyPy version is ~48 times faster, because the JIT
-can optimize across the python/numpy boundary, showing the potential of this
-approach, users are not grossly penalized for writing their loops in Python.
+``iterate`` is also interesting, but for entirely different reasons. On CPython
+it spends most of the time inside a Python loop; the PyPy version is ~48 times
+faster, because the JIT can optimize across the python/numpy boundary, showing
+the potential of this approach, users are not grossly penalized for writing
+their loops in Python.
The drawback of this approach is that we need to reimplement numpy in RPython,
which takes time. A very rough estimate is that it would be possible to
@@ -72,8 +71,8 @@
The good starting point for helping would be to look at what's already
implemented in micronumpy modules and try extending it. Adding a `-` operator
or adding integers would be an interesting start. Drop by on #pypy on
-irc.freenode.net or get in contact with developers via some other channel
-if you want to help.
+irc.freenode.net or get in contact with developers via some other channel (such
+as the pypy-dev mailing list) if you want to help.
Another option would be to sponsor NumPy development. In case you're
interested, please get in touch with us or leave your email in comments.
From commits-noreply at bitbucket.org Wed May 4 18:01:05 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 18:01:05 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: Yes numexpr. Also elevate vocabulary
(ha!)
Message-ID: <20110504160105.266612A202B@codespeak.net>
Author: Maciej Fijalkowski
Branch: extradoc
Changeset: r3564:183e23de36c8
Date: 2011-05-04 18:00 +0200
http://bitbucket.org/pypy/extradoc/changeset/183e23de36c8/
Log: Yes numexpr. Also elevate vocabulary (ha!)
diff --git a/blog/draft/numpy_roadmap.rst b/blog/draft/numpy_roadmap.rst
--- a/blog/draft/numpy_roadmap.rst
+++ b/blog/draft/numpy_roadmap.rst
@@ -45,8 +45,8 @@
The exact way array addition is implemented is worth another blog post, but in
short it lazily evaluates the expression and computes it at the end, avoiding
-intermediate results. This way scales much better than numexpr (XXX numpy?) and can lead to
-speeding up all the operations that you can perform on matrices.
+intermediate results. This approach scales much better than numexpr
+and can lead to speeding up all the operations that you can perform on matrices.
The next obvious step to get even more speedups would be to extend the JIT to
use SSE operations on x86 CPUs, which should speed it up by about additional
From commits-noreply at bitbucket.org Wed May 4 18:42:45 2011
From: commits-noreply at bitbucket.org (MostAwesomeDude)
Date: Wed, 4 May 2011 18:42:45 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: micronumpy: Bring in hodgestar's float
support.
Message-ID: <20110504164245.F14E12A202C@codespeak.net>
Author: Corbin Simpson
Branch: numpy-exp
Changeset: r43889:af8ad6737b5d
Date: 2011-03-25 21:11 -0700
http://bitbucket.org/pypy/pypy/changeset/af8ad6737b5d/
Log: micronumpy: Bring in hodgestar's float support.
Had to be fairly heftily rewritten. Also, enable the tests, fix up
slightly, and make things more readable.
I have a tendency to comment and doc things. Hope this isn't a Bad
Thing.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -1,7 +1,7 @@
from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
-from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.error import operationerrfmt
from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.rpython.lltypesystem import lltype
from pypy.rlib import jit
@@ -13,21 +13,37 @@
virtualizables = ['frame'])
class ComputationFrame(object):
- _virtualizable2_ = ['valuestackdepth', 'valuestack[*]', 'local_pos',
- 'locals[*]']
+ _virtualizable2_ = ['valuestackdepth', 'valuestack[*]',
+ 'array_pos', 'arrays[*]',
+ 'float_pos', 'floats[*]',
+ ]
- def __init__(self, input):
+ def __init__(self, arrays, floats):
self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
self.valuestackdepth = 0
- self.valuestack = [0.0] * len(input)
- self.locals = input[:]
- self.local_pos = len(input)
+ self.arrays = arrays
+ self.array_pos = len(arrays)
+ self.floats = floats
+ self.float_pos = len(floats)
+ self.valuestack = [0.0] * (len(arrays) + len(floats))
- def getlocal(self):
- p = self.local_pos - 1
+ def reset(self):
+ self.valuestackdepth = 0
+ self.array_pos = len(self.arrays)
+ self.float_pos = len(self.floats)
+
+ def getarray(self):
+ p = self.array_pos - 1
assert p >= 0
- res = self.locals[p]
- self.local_pos = p
+ res = self.arrays[p]
+ self.array_pos = p
+ return res
+
+ def getfloat(self):
+ p = self.float_pos - 1
+ assert p >= 0
+ res = self.floats[p]
+ self.float_pos = p
return res
def popvalue(self):
@@ -41,12 +57,37 @@
self.valuestack[self.valuestackdepth] = v
self.valuestackdepth += 1
-def compute(bytecode, input):
- result_size = input[0].size
+class Code(object):
+ """
+ A chunk of bytecode.
+ """
+
+ def __init__(self, bytecode, arrays, floats):
+ self.bytecode = bytecode
+ self.arrays = arrays
+ self.floats = floats
+
+ def merge(self, code, other):
+ """
+ Merge this bytecode with the other bytecode, using ``code`` as the
+ bytecode instruction for performing the merge.
+ """
+
+ return Code(code + self.bytecode + other.bytecode,
+ self.arrays + other.arrays,
+ self.floats + other.floats)
+
+def compute(code):
+ """
+ Crunch a ``Code`` full of bytecode.
+ """
+
+ bytecode = code.bytecode
+ result_size = code.arrays[0].size
result = SingleDimArray(result_size)
bytecode_pos = len(bytecode) - 1
i = 0
- frame = ComputationFrame(input)
+ frame = ComputationFrame(code.arrays, code.floats)
while i < result_size:
numpy_driver.jit_merge_point(bytecode=bytecode, result=result,
result_size=result_size,
@@ -54,9 +95,8 @@
bytecode_pos=bytecode_pos)
if bytecode_pos == -1:
bytecode_pos = len(bytecode) - 1
- frame.local_pos = len(frame.locals)
+ frame.reset()
result.storage[i] = frame.valuestack[0]
- frame.valuestackdepth = 0
i += 1
numpy_driver.can_enter_jit(bytecode=bytecode, result=result,
result_size=result_size,
@@ -65,15 +105,21 @@
else:
opcode = bytecode[bytecode_pos]
if opcode == 'l':
- val = frame.getlocal().storage[i]
- frame.valuestack[frame.valuestackdepth] = val
- frame.valuestackdepth += 1
+ # Load array.
+ val = frame.getarray().storage[i]
+ frame.pushvalue(val)
+ elif opcode == 'f':
+ # Load float.
+ val = frame.getfloat()
+ frame.pushvalue(val)
elif opcode == 'a':
+ # Add.
b = frame.popvalue()
a = frame.popvalue()
frame.pushvalue(a + b)
else:
- raise NotImplementedError
+ raise NotImplementedError(
+ "Can't handle bytecode instruction %s" % opcode)
bytecode_pos -= 1
return result
@@ -81,37 +127,56 @@
class BaseArray(Wrappable):
def force(self):
- bytecode, stack = self.compile()
+ code = self.compile()
try:
- bytecode = JITCODES[bytecode]
+ code.bytecode = JITCODES[code.bytecode]
except KeyError:
- JITCODES[bytecode] = bytecode
+ JITCODES[code.bytecode] = code.bytecode
# the point of above hacks is to intern the bytecode string
# otherwise we have to compile new assembler each time, which sucks
# (we still have to compile new bytecode, but too bad)
- return compute(bytecode, stack)
+ return compute(code)
def descr_add(self, space, w_other):
- return space.wrap(Add(self, w_other))
+ if isinstance(w_other, BaseArray):
+ return space.wrap(Add(self, w_other))
+ else:
+ return space.wrap(FloatAdd(self, space.float_w(w_other)))
def compile(self):
raise NotImplementedError("abstract base class")
class Add(BaseArray):
+ """
+ Intermediate class for adding arrays.
+ """
+
def __init__(self, left, right):
- assert isinstance(left, BaseArray)
- assert isinstance(right, BaseArray)
self.left = left
self.right = right
def compile(self):
- left_bc, left_stack = self.left.compile()
- right_bc, right_stack = self.right.compile()
- return 'a' + left_bc + right_bc, left_stack + right_stack
+ left_code = self.left.compile()
+ right_code = self.right.compile()
+ return left_code.merge('a', right_code)
+
+class FloatAdd(BaseArray):
+ """
+ Intermediate class for adding an array and a float.
+ """
+
+ def __init__(self, left, right):
+ self.left = left
+ self.right = right
+
+ def compile(self):
+ left_code = self.left.compile()
+ right_code = Code('f', [], [self.right])
+ return left_code.merge('a', right_code)
BaseArray.typedef = TypeDef(
'Operation',
- force=interp2app(BaseArray.force),
+ force = interp2app(BaseArray.force),
__add__ = interp2app(BaseArray.descr_add),
)
@@ -123,7 +188,7 @@
# XXX find out why test_jit explodes with trackign of allocations
def compile(self):
- return "l", [self]
+ return Code('l', [self], [])
@unwrap_spec(item=int)
def descr_getitem(self, space, item):
@@ -173,4 +238,3 @@
__add__ = interp2app(BaseArray.descr_add),
force = interp2app(SingleDimArray.force),
)
-
diff --git a/pypy/module/micronumpy/test/test_jit.py b/pypy/module/micronumpy/test/test_jit.py
--- a/pypy/module/micronumpy/test/test_jit.py
+++ b/pypy/module/micronumpy/test/test_jit.py
@@ -1,6 +1,4 @@
-
-from pypy.module.micronumpy.numarray import SingleDimArray, Add
-from pypy.conftest import gettestobjspace
+from pypy.module.micronumpy.numarray import SingleDimArray, Add, FloatAdd
from pypy.jit.metainterp.test.test_basic import LLJitMixin
class FakeSpace(object):
@@ -21,8 +19,25 @@
v = ar
return v.force().storage[3]
- self.meta_interp(f, [5], listops=True, backendopt=True)
+ result = self.meta_interp(f, [5], listops=True, backendopt=True)
self.check_loops({'getarrayitem_raw': 2, 'float_add': 1,
'setarrayitem_raw': 1, 'int_add': 1,
'int_lt': 1, 'guard_true': 1, 'jump': 1})
-
+ assert result == f(5)
+
+ def test_floatadd(self):
+ space = self.space
+
+ def f(i):
+ ar = SingleDimArray(i)
+ if i:
+ v = FloatAdd(ar, 4.5)
+ else:
+ v = ar
+ return v.force().storage[3]
+
+ result = self.meta_interp(f, [5], listops=True, backendopt=True)
+ self.check_loops({"getarrayitem_gc": 2, "float_add": 2,
+ "setarrayitem_gc": 1, "int_add": 1,
+ "int_lt": 1, "guard_true": 1, "jump": 1})
+ assert result == f(5)
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -25,9 +25,17 @@
b = b.force()
assert b[2] == 2 + 2
+ def test_floatadd(self):
+ from numpy import array
+ a = array(range(5))
+ b = a + 5
+ b = b.force()
+ for i in range(5):
+ assert b[i] == i + 5
+
+
class AppTestNumpy(object):
def setup_class(cls):
- py.test.skip("skip")
cls.space = gettestobjspace(usemodules=('micronumpy',))
def test_zeroes(self):
@@ -67,7 +75,6 @@
class AppTestMultiDim(object):
def setup_class(cls):
- py.test.skip("skip")
cls.space = gettestobjspace(usemodules=('micronumpy',))
def test_multidim(self):
From commits-noreply at bitbucket.org Wed May 4 18:42:47 2011
From: commits-noreply at bitbucket.org (MostAwesomeDude)
Date: Wed, 4 May 2011 18:42:47 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: micronumpy: Add multiply opcode/compile,
and test.
Message-ID: <20110504164247.20DCA2A202C@codespeak.net>
Author: Corbin Simpson
Branch: numpy-exp
Changeset: r43890:d5eff8d4c09b
Date: 2011-03-25 21:24 -0700
http://bitbucket.org/pypy/pypy/changeset/d5eff8d4c09b/
Log: micronumpy: Add multiply opcode/compile, and test.
Not sure what to do with the JIT tests. They seem very expansive.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -117,6 +117,11 @@
b = frame.popvalue()
a = frame.popvalue()
frame.pushvalue(a + b)
+ elif opcode == 'm':
+ # Multiply.
+ b = frame.popvalue()
+ a = frame.popvalue()
+ frame.pushvalue(a * b)
else:
raise NotImplementedError(
"Can't handle bytecode instruction %s" % opcode)
@@ -139,45 +144,52 @@
def descr_add(self, space, w_other):
if isinstance(w_other, BaseArray):
- return space.wrap(Add(self, w_other))
+ return space.wrap(BinOp('a', self, w_other))
else:
- return space.wrap(FloatAdd(self, space.float_w(w_other)))
+ return space.wrap(BinOp('a', self,
+ FloatWrapper(space.float_w(w_other))))
+
+ def descr_mul(self, space, w_other):
+ if isinstance(w_other, BaseArray):
+ return space.wrap(BinOp('m', self, w_other))
+ else:
+ return space.wrap(BinOp('m', self,
+ FloatWrapper(space.float_w(w_other))))
def compile(self):
raise NotImplementedError("abstract base class")
-class Add(BaseArray):
+class FloatWrapper(BaseArray):
"""
- Intermediate class for adding arrays.
+ Intermediate class representing a float literal.
"""
- def __init__(self, left, right):
+ def __init__(self, float_value):
+ self.float_value = float_value
+
+ def compile(self):
+ return Code('f', [], [self.float_value])
+
+class BinOp(BaseArray):
+ """
+ Intermediate class for performing binary operations.
+ """
+
+ def __init__(self, opcode, left, right):
+ self.opcode = opcode
self.left = left
self.right = right
def compile(self):
left_code = self.left.compile()
right_code = self.right.compile()
- return left_code.merge('a', right_code)
-
-class FloatAdd(BaseArray):
- """
- Intermediate class for adding an array and a float.
- """
-
- def __init__(self, left, right):
- self.left = left
- self.right = right
-
- def compile(self):
- left_code = self.left.compile()
- right_code = Code('f', [], [self.right])
- return left_code.merge('a', right_code)
+ return left_code.merge(self.opcode, right_code)
BaseArray.typedef = TypeDef(
'Operation',
force = interp2app(BaseArray.force),
__add__ = interp2app(BaseArray.descr_add),
+ __mul__ = interp2app(BaseArray.descr_mul),
)
class SingleDimArray(BaseArray):
@@ -236,5 +248,6 @@
__getitem__ = interp2app(SingleDimArray.descr_getitem),
__setitem__ = interp2app(SingleDimArray.descr_setitem),
__add__ = interp2app(BaseArray.descr_add),
+ __mul__ = interp2app(BaseArray.descr_mul),
force = interp2app(SingleDimArray.force),
)
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -1,4 +1,3 @@
-
import py
from pypy.conftest import gettestobjspace
@@ -23,7 +22,8 @@
a = array(range(5))
b = a + a
b = b.force()
- assert b[2] == 2 + 2
+ for i in range(5):
+ assert b[i] == i + i
def test_floatadd(self):
from numpy import array
@@ -33,6 +33,21 @@
for i in range(5):
assert b[i] == i + 5
+ def test_mul(self):
+ from numpy import array
+ a = array(range(5))
+ b = a * a
+ b = b.force()
+ for i in range(5):
+ assert b[i] == i * i
+
+ def test_floatmul(self):
+ from numpy import array
+ a = array(range(5))
+ b = a * 5
+ b = b.force()
+ for i in range(5):
+ assert b[i] == i * 5
class AppTestNumpy(object):
def setup_class(cls):
From commits-noreply at bitbucket.org Wed May 4 18:42:48 2011
From: commits-noreply at bitbucket.org (MostAwesomeDude)
Date: Wed, 4 May 2011 18:42:48 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: micronumpy: Test that separate arrays
actually add correctly.
Message-ID: <20110504164248.DF3732A2031@codespeak.net>
Author: Corbin Simpson
Branch: numpy-exp
Changeset: r43891:a69e4ebdb978
Date: 2011-03-25 22:55 -0700
http://bitbucket.org/pypy/pypy/changeset/a69e4ebdb978/
Log: micronumpy: Test that separate arrays actually add correctly.
And they do. Rejoice?
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -6,9 +6,11 @@
cls.space = gettestobjspace(usemodules=('micronumpy',))
def test_init(self):
- from numpy import array, zeros
+ from numpy import zeros
a = zeros(15)
+ # Check that storage was actually zero'd.
assert a[10] == 0.0
+ # And check that changes stick.
a[13] = 5.3
assert a[13] == 5.3
@@ -25,7 +27,16 @@
for i in range(5):
assert b[i] == i + i
- def test_floatadd(self):
+ def test_add_other(self):
+ from numpy import array
+ a = array(range(5))
+ b = array(reversed(range(5)))
+ c = a + b
+ c = c.force()
+ for i in range(5):
+ assert c[i] == 4
+
+ def test_add_constant(self):
from numpy import array
a = array(range(5))
b = a + 5
@@ -41,7 +52,7 @@
for i in range(5):
assert b[i] == i * i
- def test_floatmul(self):
+ def test_mul_constant(self):
from numpy import array
a = array(range(5))
b = a * 5
From commits-noreply at bitbucket.org Wed May 4 18:42:51 2011
From: commits-noreply at bitbucket.org (MostAwesomeDude)
Date: Wed, 4 May 2011 18:42:51 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: translator/goal: Fix up standalone numpy.
Message-ID: <20110504164251.F15D22A2037@codespeak.net>
Author: Corbin Simpson
Branch: numpy-exp
Changeset: r43892:cb21bb375261
Date: 2011-03-25 23:25 -0700
http://bitbucket.org/pypy/pypy/changeset/cb21bb375261/
Log: translator/goal: Fix up standalone numpy.
diff --git a/pypy/translator/goal/targetnumpystandalone.py b/pypy/translator/goal/targetnumpystandalone.py
--- a/pypy/translator/goal/targetnumpystandalone.py
+++ b/pypy/translator/goal/targetnumpystandalone.py
@@ -10,7 +10,7 @@
"""
import time
-from pypy.module.micronumpy.numarray import SingleDimArray, compute
+from pypy.module.micronumpy.numarray import SingleDimArray, Code, compute
from pypy.jit.codewriter.policy import JitPolicy
def create_array(size):
@@ -43,8 +43,9 @@
arrays.append(create_array(size))
for i in range(no_floats):
floats.append(float(i + 1))
+ code = Code(bytecode, arrays, floats)
t0 = time.time()
- compute(bytecode, arrays)
+ compute(code)
print "bytecode:", bytecode, "size:", size
print "took:", time.time() - t0
return 0
From commits-noreply at bitbucket.org Wed May 4 18:42:53 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 18:42:53 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: merge MostAwesomeDude's branch
Message-ID: <20110504164253.B1B1F2A2035@codespeak.net>
Author: Maciej Fijalkowski
Branch: numpy-exp
Changeset: r43893:7838dec7ffe0
Date: 2011-05-04 18:03 +0200
http://bitbucket.org/pypy/pypy/changeset/7838dec7ffe0/
Log: merge MostAwesomeDude's branch
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -1,7 +1,7 @@
from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
-from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.error import operationerrfmt
from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.rpython.lltypesystem import lltype
from pypy.rlib import jit
@@ -13,21 +13,37 @@
virtualizables = ['frame'])
class ComputationFrame(object):
- _virtualizable2_ = ['valuestackdepth', 'valuestack[*]', 'local_pos',
- 'locals[*]']
+ _virtualizable2_ = ['valuestackdepth', 'valuestack[*]',
+ 'array_pos', 'arrays[*]',
+ 'float_pos', 'floats[*]',
+ ]
- def __init__(self, input):
+ def __init__(self, arrays, floats):
self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
self.valuestackdepth = 0
- self.valuestack = [0.0] * len(input)
- self.locals = input[:]
- self.local_pos = len(input)
+ self.arrays = arrays
+ self.array_pos = len(arrays)
+ self.floats = floats
+ self.float_pos = len(floats)
+ self.valuestack = [0.0] * (len(arrays) + len(floats))
- def getlocal(self):
- p = self.local_pos - 1
+ def reset(self):
+ self.valuestackdepth = 0
+ self.array_pos = len(self.arrays)
+ self.float_pos = len(self.floats)
+
+ def getarray(self):
+ p = self.array_pos - 1
assert p >= 0
- res = self.locals[p]
- self.local_pos = p
+ res = self.arrays[p]
+ self.array_pos = p
+ return res
+
+ def getfloat(self):
+ p = self.float_pos - 1
+ assert p >= 0
+ res = self.floats[p]
+ self.float_pos = p
return res
def popvalue(self):
@@ -41,12 +57,37 @@
self.valuestack[self.valuestackdepth] = v
self.valuestackdepth += 1
-def compute(bytecode, input):
- result_size = input[0].size
+class Code(object):
+ """
+ A chunk of bytecode.
+ """
+
+ def __init__(self, bytecode, arrays, floats):
+ self.bytecode = bytecode
+ self.arrays = arrays
+ self.floats = floats
+
+ def merge(self, code, other):
+ """
+ Merge this bytecode with the other bytecode, using ``code`` as the
+ bytecode instruction for performing the merge.
+ """
+
+ return Code(code + self.bytecode + other.bytecode,
+ self.arrays + other.arrays,
+ self.floats + other.floats)
+
+def compute(code):
+ """
+ Crunch a ``Code`` full of bytecode.
+ """
+
+ bytecode = code.bytecode
+ result_size = code.arrays[0].size
result = SingleDimArray(result_size)
bytecode_pos = len(bytecode) - 1
i = 0
- frame = ComputationFrame(input)
+ frame = ComputationFrame(code.arrays, code.floats)
while i < result_size:
numpy_driver.jit_merge_point(bytecode=bytecode, result=result,
result_size=result_size,
@@ -54,9 +95,8 @@
bytecode_pos=bytecode_pos)
if bytecode_pos == -1:
bytecode_pos = len(bytecode) - 1
- frame.local_pos = len(frame.locals)
+ frame.reset()
result.storage[i] = frame.valuestack[0]
- frame.valuestackdepth = 0
i += 1
numpy_driver.can_enter_jit(bytecode=bytecode, result=result,
result_size=result_size,
@@ -65,15 +105,26 @@
else:
opcode = bytecode[bytecode_pos]
if opcode == 'l':
- val = frame.getlocal().storage[i]
- frame.valuestack[frame.valuestackdepth] = val
- frame.valuestackdepth += 1
+ # Load array.
+ val = frame.getarray().storage[i]
+ frame.pushvalue(val)
+ elif opcode == 'f':
+ # Load float.
+ val = frame.getfloat()
+ frame.pushvalue(val)
elif opcode == 'a':
+ # Add.
b = frame.popvalue()
a = frame.popvalue()
frame.pushvalue(a + b)
+ elif opcode == 'm':
+ # Multiply.
+ b = frame.popvalue()
+ a = frame.popvalue()
+ frame.pushvalue(a * b)
else:
- raise NotImplementedError
+ raise NotImplementedError(
+ "Can't handle bytecode instruction %s" % opcode)
bytecode_pos -= 1
return result
@@ -81,38 +132,64 @@
class BaseArray(Wrappable):
def force(self):
- bytecode, stack = self.compile()
+ code = self.compile()
try:
- bytecode = JITCODES[bytecode]
+ code.bytecode = JITCODES[code.bytecode]
except KeyError:
- JITCODES[bytecode] = bytecode
+ JITCODES[code.bytecode] = code.bytecode
# the point of above hacks is to intern the bytecode string
# otherwise we have to compile new assembler each time, which sucks
# (we still have to compile new bytecode, but too bad)
- return compute(bytecode, stack)
+ return compute(code)
def descr_add(self, space, w_other):
- return space.wrap(Add(self, w_other))
+ if isinstance(w_other, BaseArray):
+ return space.wrap(BinOp('a', self, w_other))
+ else:
+ return space.wrap(BinOp('a', self,
+ FloatWrapper(space.float_w(w_other))))
+
+ def descr_mul(self, space, w_other):
+ if isinstance(w_other, BaseArray):
+ return space.wrap(BinOp('m', self, w_other))
+ else:
+ return space.wrap(BinOp('m', self,
+ FloatWrapper(space.float_w(w_other))))
def compile(self):
raise NotImplementedError("abstract base class")
-class Add(BaseArray):
- def __init__(self, left, right):
- assert isinstance(left, BaseArray)
- assert isinstance(right, BaseArray)
+class FloatWrapper(BaseArray):
+ """
+ Intermediate class representing a float literal.
+ """
+
+ def __init__(self, float_value):
+ self.float_value = float_value
+
+ def compile(self):
+ return Code('f', [], [self.float_value])
+
+class BinOp(BaseArray):
+ """
+ Intermediate class for performing binary operations.
+ """
+
+ def __init__(self, opcode, left, right):
+ self.opcode = opcode
self.left = left
self.right = right
def compile(self):
- left_bc, left_stack = self.left.compile()
- right_bc, right_stack = self.right.compile()
- return 'a' + left_bc + right_bc, left_stack + right_stack
+ left_code = self.left.compile()
+ right_code = self.right.compile()
+ return left_code.merge(self.opcode, right_code)
BaseArray.typedef = TypeDef(
'Operation',
- force=interp2app(BaseArray.force),
+ force = interp2app(BaseArray.force),
__add__ = interp2app(BaseArray.descr_add),
+ __mul__ = interp2app(BaseArray.descr_mul),
)
class SingleDimArray(BaseArray):
@@ -123,7 +200,7 @@
# XXX find out why test_jit explodes with trackign of allocations
def compile(self):
- return "l", [self]
+ return Code('l', [self], [])
@unwrap_spec(item=int)
def descr_getitem(self, space, item):
@@ -171,6 +248,6 @@
__getitem__ = interp2app(SingleDimArray.descr_getitem),
__setitem__ = interp2app(SingleDimArray.descr_setitem),
__add__ = interp2app(BaseArray.descr_add),
+ __mul__ = interp2app(BaseArray.descr_mul),
force = interp2app(SingleDimArray.force),
)
-
diff --git a/pypy/module/micronumpy/test/test_jit.py b/pypy/module/micronumpy/test/test_jit.py
--- a/pypy/module/micronumpy/test/test_jit.py
+++ b/pypy/module/micronumpy/test/test_jit.py
@@ -1,6 +1,4 @@
-
-from pypy.module.micronumpy.numarray import SingleDimArray, Add
-from pypy.conftest import gettestobjspace
+from pypy.module.micronumpy.numarray import SingleDimArray, Add, FloatAdd
from pypy.jit.metainterp.test.test_basic import LLJitMixin
class FakeSpace(object):
@@ -21,8 +19,25 @@
v = ar
return v.force().storage[3]
- self.meta_interp(f, [5], listops=True, backendopt=True)
+ result = self.meta_interp(f, [5], listops=True, backendopt=True)
self.check_loops({'getarrayitem_raw': 2, 'float_add': 1,
'setarrayitem_raw': 1, 'int_add': 1,
'int_lt': 1, 'guard_true': 1, 'jump': 1})
-
+ assert result == f(5)
+
+ def test_floatadd(self):
+ space = self.space
+
+ def f(i):
+ ar = SingleDimArray(i)
+ if i:
+ v = FloatAdd(ar, 4.5)
+ else:
+ v = ar
+ return v.force().storage[3]
+
+ result = self.meta_interp(f, [5], listops=True, backendopt=True)
+ self.check_loops({"getarrayitem_gc": 2, "float_add": 2,
+ "setarrayitem_gc": 1, "int_add": 1,
+ "int_lt": 1, "guard_true": 1, "jump": 1})
+ assert result == f(5)
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -1,4 +1,3 @@
-
import py
from pypy.conftest import gettestobjspace
@@ -7,9 +6,11 @@
cls.space = gettestobjspace(usemodules=('micronumpy',))
def test_init(self):
- from numpy import array, zeros
+ from numpy import zeros
a = zeros(15)
+ # Check that storage was actually zero'd.
assert a[10] == 0.0
+ # And check that changes stick.
a[13] = 5.3
assert a[13] == 5.3
@@ -23,11 +24,44 @@
a = array(range(5))
b = a + a
b = b.force()
- assert b[2] == 2 + 2
+ for i in range(5):
+ assert b[i] == i + i
+
+ def test_add_other(self):
+ from numpy import array
+ a = array(range(5))
+ b = array(reversed(range(5)))
+ c = a + b
+ c = c.force()
+ for i in range(5):
+ assert c[i] == 4
+
+ def test_add_constant(self):
+ from numpy import array
+ a = array(range(5))
+ b = a + 5
+ b = b.force()
+ for i in range(5):
+ assert b[i] == i + 5
+
+ def test_mul(self):
+ from numpy import array
+ a = array(range(5))
+ b = a * a
+ b = b.force()
+ for i in range(5):
+ assert b[i] == i * i
+
+ def test_mul_constant(self):
+ from numpy import array
+ a = array(range(5))
+ b = a * 5
+ b = b.force()
+ for i in range(5):
+ assert b[i] == i * 5
class AppTestNumpy(object):
def setup_class(cls):
- py.test.skip("skip")
cls.space = gettestobjspace(usemodules=('micronumpy',))
def test_zeroes(self):
@@ -67,7 +101,6 @@
class AppTestMultiDim(object):
def setup_class(cls):
- py.test.skip("skip")
cls.space = gettestobjspace(usemodules=('micronumpy',))
def test_multidim(self):
diff --git a/pypy/translator/goal/targetnumpystandalone.py b/pypy/translator/goal/targetnumpystandalone.py
--- a/pypy/translator/goal/targetnumpystandalone.py
+++ b/pypy/translator/goal/targetnumpystandalone.py
@@ -10,7 +10,7 @@
"""
import time
-from pypy.module.micronumpy.numarray import SingleDimArray, compute
+from pypy.module.micronumpy.numarray import SingleDimArray, Code, compute
from pypy.jit.codewriter.policy import JitPolicy
def create_array(size):
@@ -43,8 +43,9 @@
arrays.append(create_array(size))
for i in range(no_floats):
floats.append(float(i + 1))
+ code = Code(bytecode, arrays, floats)
t0 = time.time()
- compute(bytecode, arrays)
+ compute(code)
print "bytecode:", bytecode, "size:", size
print "took:", time.time() - t0
return 0
From commits-noreply at bitbucket.org Wed May 4 23:20:45 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Wed, 4 May 2011 23:20:45 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: fix tests from bad merges, bad fijal,
no cookie
Message-ID: <20110504212045.942672A202B@codespeak.net>
Author: Maciej Fijalkowski
Branch: numpy-exp
Changeset: r43894:0202bb3a6d74
Date: 2011-05-04 23:20 +0200
http://bitbucket.org/pypy/pypy/changeset/0202bb3a6d74/
Log: fix tests from bad merges, bad fijal, no cookie
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -4,6 +4,7 @@
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.rpython.lltypesystem import lltype
from pypy.rlib import jit
+from pypy.rlib.nonconst import NonConstant
TP = lltype.Array(lltype.Float, hints={'nolength': True})
@@ -24,6 +25,8 @@
self.arrays = arrays
self.array_pos = len(arrays)
self.floats = floats
+ if NonConstant(0):
+ self.floats = [3.5] # annotator hack for test_jit
self.float_pos = len(floats)
self.valuestack = [0.0] * (len(arrays) + len(floats))
diff --git a/pypy/module/micronumpy/test/test_jit.py b/pypy/module/micronumpy/test/test_jit.py
--- a/pypy/module/micronumpy/test/test_jit.py
+++ b/pypy/module/micronumpy/test/test_jit.py
@@ -1,5 +1,5 @@
-from pypy.module.micronumpy.numarray import SingleDimArray, Add, FloatAdd
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.module.micronumpy.numarray import SingleDimArray, BinOp, FloatWrapper
+from pypy.jit.metainterp.test.support import LLJitMixin
class FakeSpace(object):
pass
@@ -14,7 +14,7 @@
def f(i):
ar = SingleDimArray(i)
if i:
- v = Add(ar, ar)
+ v = BinOp('a', ar, ar)
else:
v = ar
return v.force().storage[3]
@@ -31,13 +31,13 @@
def f(i):
ar = SingleDimArray(i)
if i:
- v = FloatAdd(ar, 4.5)
+ v = BinOp('a', ar, FloatWrapper(4.5))
else:
v = ar
return v.force().storage[3]
result = self.meta_interp(f, [5], listops=True, backendopt=True)
- self.check_loops({"getarrayitem_gc": 2, "float_add": 2,
- "setarrayitem_gc": 1, "int_add": 1,
+ self.check_loops({"getarrayitem_raw": 1, "float_add": 1,
+ "setarrayitem_raw": 1, "int_add": 1,
"int_lt": 1, "guard_true": 1, "jump": 1})
assert result == f(5)
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -62,6 +62,7 @@
class AppTestNumpy(object):
def setup_class(cls):
+ py.test.skip("unimplemented")
cls.space = gettestobjspace(usemodules=('micronumpy',))
def test_zeroes(self):
@@ -101,6 +102,7 @@
class AppTestMultiDim(object):
def setup_class(cls):
+ py.test.skip("unimplemented")
cls.space = gettestobjspace(usemodules=('micronumpy',))
def test_multidim(self):
From commits-noreply at bitbucket.org Thu May 5 00:33:29 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 00:33:29 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Implemented subtraction in numpy (thanks
to brentp). Also refactored to metaprogram (this is why we
use pypy).
Message-ID: <20110504223329.C5CE436C208@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43896:52cadacd06c8
Date: 2011-05-04 18:33 -0400
http://bitbucket.org/pypy/pypy/changeset/52cadacd06c8/
Log: Implemented subtraction in numpy (thanks to brentp). Also
refactored to metaprogram (this is why we use pypy).
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -1,10 +1,12 @@
from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.rpython.lltypesystem import lltype
from pypy.rlib import jit
from pypy.rlib.nonconst import NonConstant
+from pypy.rpython.lltypesystem import lltype
+from pypy.tool.sourcetools import func_with_new_name
+
TP = lltype.Array(lltype.Float, hints={'nolength': True})
@@ -117,13 +119,18 @@
frame.pushvalue(val)
elif opcode == 'a':
# Add.
+ a = frame.popvalue()
b = frame.popvalue()
+ frame.pushvalue(a + b)
+ elif opcode == 's':
+ # Subtract
a = frame.popvalue()
- frame.pushvalue(a + b)
+ b = frame.popvalue()
+ frame.pushvalue(a - b)
elif opcode == 'm':
# Multiply.
+ a = frame.popvalue()
b = frame.popvalue()
- a = frame.popvalue()
frame.pushvalue(a * b)
else:
raise NotImplementedError(
@@ -145,19 +152,21 @@
# (we still have to compile new bytecode, but too bad)
return compute(code)
- def descr_add(self, space, w_other):
- if isinstance(w_other, BaseArray):
- return space.wrap(BinOp('a', self, w_other))
- else:
- return space.wrap(BinOp('a', self,
- FloatWrapper(space.float_w(w_other))))
+ def _binop_impl(bytecode):
+ def impl(self, space, w_other):
+ if isinstance(w_other, BaseArray):
+ return space.wrap(BinOp(bytecode, self, w_other))
+ else:
+ return space.wrap(BinOp(
+ bytecode,
+ self,
+ FloatWrapper(space.float_w(w_other))
+ ))
+ return func_with_new_name(impl, "binop_%s_impl" % bytecode)
- def descr_mul(self, space, w_other):
- if isinstance(w_other, BaseArray):
- return space.wrap(BinOp('m', self, w_other))
- else:
- return space.wrap(BinOp('m', self,
- FloatWrapper(space.float_w(w_other))))
+ descr_add = _binop_impl("a")
+ descr_mul = _binop_impl("m")
+ descr_sub = _binop_impl("s")
def compile(self):
raise NotImplementedError("abstract base class")
@@ -192,6 +201,7 @@
'Operation',
force = interp2app(BaseArray.force),
__add__ = interp2app(BaseArray.descr_add),
+ __sub__ = interp2app(BaseArray.descr_sub),
__mul__ = interp2app(BaseArray.descr_mul),
)
@@ -251,6 +261,7 @@
__getitem__ = interp2app(SingleDimArray.descr_getitem),
__setitem__ = interp2app(SingleDimArray.descr_setitem),
__add__ = interp2app(BaseArray.descr_add),
+ __sub__ = interp2app(BaseArray.descr_sub),
__mul__ = interp2app(BaseArray.descr_mul),
force = interp2app(SingleDimArray.force),
)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -44,6 +44,28 @@
for i in range(5):
assert b[i] == i + 5
+ def test_subtract(self):
+ from numpy import array
+ a = array(range(5))
+ b = (a - a).force()
+ for i in range(5):
+ assert b[i] == 0
+
+ def test_subtract_other(self):
+ from numpy import array
+ a = array(range(5))
+ b = array([1, 1, 1, 1, 1])
+ c = (a - b).force()
+ for i in range(5):
+ assert c[i] == i - 1
+
+ def test_subtract_constant(self):
+ from numpy import array
+ a = array(range(5))
+ b = (a - 5).force()
+ for i in range(5):
+ assert b[i] == i - 5
+
def test_mul(self):
from numpy import array
a = array(range(5))
@@ -64,12 +86,12 @@
def setup_class(cls):
py.test.skip("unimplemented")
cls.space = gettestobjspace(usemodules=('micronumpy',))
-
+
def test_zeroes(self):
from numpy import zeros
ar = zeros(3, dtype=int)
assert ar[0] == 0
-
+
def test_setitem_getitem(self):
from numpy import zeros
ar = zeros(8, dtype=int)
From commits-noreply at bitbucket.org Thu May 5 00:39:48 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 00:39:48 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: implemented division in numpy,
thanks bretp
Message-ID: <20110504223948.E1FA236C208@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43897:f87795f00a56
Date: 2011-05-04 18:38 -0400
http://bitbucket.org/pypy/pypy/changeset/f87795f00a56/
Log: implemented division in numpy, thanks bretp
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -132,6 +132,10 @@
a = frame.popvalue()
b = frame.popvalue()
frame.pushvalue(a * b)
+ elif opcode == 'd':
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a / b)
else:
raise NotImplementedError(
"Can't handle bytecode instruction %s" % opcode)
@@ -165,8 +169,9 @@
return func_with_new_name(impl, "binop_%s_impl" % bytecode)
descr_add = _binop_impl("a")
+ descr_sub = _binop_impl("s")
descr_mul = _binop_impl("m")
- descr_sub = _binop_impl("s")
+ descr_div = _binop_impl("d")
def compile(self):
raise NotImplementedError("abstract base class")
@@ -203,6 +208,7 @@
__add__ = interp2app(BaseArray.descr_add),
__sub__ = interp2app(BaseArray.descr_sub),
__mul__ = interp2app(BaseArray.descr_mul),
+ __div__ = interp2app(BaseArray.descr_div),
)
class SingleDimArray(BaseArray):
@@ -263,5 +269,6 @@
__add__ = interp2app(BaseArray.descr_add),
__sub__ = interp2app(BaseArray.descr_sub),
__mul__ = interp2app(BaseArray.descr_mul),
+ __div__ = interp2app(BaseArray.descr_div),
force = interp2app(SingleDimArray.force),
)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -82,6 +82,28 @@
for i in range(5):
assert b[i] == i * 5
+ def test_div(self):
+ from numpy import array
+ a = array(range(1, 6))
+ b = (a / a).force()
+ for i in range(5):
+ assert b[i] == 1
+
+ def test_div_other(self):
+ from numpy import array
+ a = array(range(5))
+ b = array([2, 2, 2, 2, 2])
+ c = (a / b).force()
+ for i in range(5):
+ assert c[i] == i / 2.0
+
+ def test_div_constant(self):
+ from numpy import array
+ a = array(range(5))
+ b = (a / 5.0).force()
+ for i in range(5):
+ assert b[i] == i / 5.0
+
class AppTestNumpy(object):
def setup_class(cls):
py.test.skip("unimplemented")
From commits-noreply at bitbucket.org Thu May 5 00:39:50 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 00:39:50 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Rename test_jit to test_zjit so pytest
runs it last.
Message-ID: <20110504223950.0BEC336C208@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43898:b36b1f411dfc
Date: 2011-05-04 18:39 -0400
http://bitbucket.org/pypy/pypy/changeset/b36b1f411dfc/
Log: Rename test_jit to test_zjit so pytest runs it last.
diff --git a/pypy/module/micronumpy/test/test_jit.py b/pypy/module/micronumpy/test/test_zjit.py
rename from pypy/module/micronumpy/test/test_jit.py
rename to pypy/module/micronumpy/test/test_zjit.py
From commits-noreply at bitbucket.org Thu May 5 01:04:02 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 01:04:02 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Make auto-lazy-forcing not break
semantics.
Message-ID: <20110504230402.220902A202B@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43899:1486788fda44
Date: 2011-05-04 19:03 -0400
http://bitbucket.org/pypy/pypy/changeset/1486788fda44/
Log: Make auto-lazy-forcing not break semantics.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -145,6 +145,9 @@
JITCODES = {}
class BaseArray(Wrappable):
+ def __init__(self):
+ self.invalidates = []
+
def force(self):
code = self.compile()
try:
@@ -156,16 +159,24 @@
# (we still have to compile new bytecode, but too bad)
return compute(code)
+ def invalidated(self):
+ for arr in self.invalidates:
+ arr.force_if_needed()
+ self.invalidates = []
+
def _binop_impl(bytecode):
def impl(self, space, w_other):
if isinstance(w_other, BaseArray):
- return space.wrap(BinOp(bytecode, self, w_other))
+ res = space.wrap(BinOp(bytecode, self, w_other))
+ w_other.invalidates.append(res)
else:
- return space.wrap(BinOp(
+ res = space.wrap(BinOp(
bytecode,
self,
FloatWrapper(space.float_w(w_other))
))
+ self.invalidates.append(res)
+ return res
return func_with_new_name(impl, "binop_%s_impl" % bytecode)
descr_add = _binop_impl("a")
@@ -182,6 +193,7 @@
"""
def __init__(self, float_value):
+ BaseArray.__init__(self)
self.float_value = float_value
def compile(self):
@@ -193,18 +205,39 @@
"""
def __init__(self, opcode, left, right):
+ BaseArray.__init__(self)
self.opcode = opcode
self.left = left
self.right = right
+ self.forced_result = None
+
def compile(self):
left_code = self.left.compile()
right_code = self.right.compile()
return left_code.merge(self.opcode, right_code)
-BaseArray.typedef = TypeDef(
+ def force_if_needed(self):
+ if self.forced_result is None:
+ self.forced_result = self.force()
+
+ @unwrap_spec(item=int)
+ def descr_getitem(self, space, item):
+ self.force_if_needed()
+ return self.forced_result.descr_getitem(space, item)
+
+ @unwrap_spec(item=int, value=float)
+ def descr_setitem(self, space, item, value):
+ self.forced_if_needed()
+ self.invalidated()
+ return self.forced_result.descr_setitem(space, item, value)
+
+
+BinOp.typedef = TypeDef(
'Operation',
- force = interp2app(BaseArray.force),
+ __getitem__ = interp2app(BinOp.descr_getitem),
+ __setitem__ = interp2app(BinOp.descr_setitem),
+
__add__ = interp2app(BaseArray.descr_add),
__sub__ = interp2app(BaseArray.descr_sub),
__mul__ = interp2app(BaseArray.descr_mul),
@@ -213,6 +246,7 @@
class SingleDimArray(BaseArray):
def __init__(self, size):
+ BaseArray.__init__(self)
self.size = size
self.storage = lltype.malloc(TP, size, zero=True,
flavor='raw', track_allocation=False)
@@ -239,11 +273,9 @@
if item > self.size:
raise operationerrfmt(space.w_TypeError,
'%d above array size', item)
+ self.invalidated()
self.storage[item] = value
- def force(self):
- return self
-
def __del__(self):
lltype.free(self.storage, flavor='raw')
@@ -270,5 +302,4 @@
__sub__ = interp2app(BaseArray.descr_sub),
__mul__ = interp2app(BaseArray.descr_mul),
__div__ = interp2app(BaseArray.descr_div),
- force = interp2app(SingleDimArray.force),
)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -23,7 +23,6 @@
from numpy import array
a = array(range(5))
b = a + a
- b = b.force()
for i in range(5):
assert b[i] == i + i
@@ -32,7 +31,6 @@
a = array(range(5))
b = array(reversed(range(5)))
c = a + b
- c = c.force()
for i in range(5):
assert c[i] == 4
@@ -40,14 +38,13 @@
from numpy import array
a = array(range(5))
b = a + 5
- b = b.force()
for i in range(5):
assert b[i] == i + 5
def test_subtract(self):
from numpy import array
a = array(range(5))
- b = (a - a).force()
+ b = a - a
for i in range(5):
assert b[i] == 0
@@ -55,14 +52,14 @@
from numpy import array
a = array(range(5))
b = array([1, 1, 1, 1, 1])
- c = (a - b).force()
+ c = a - b
for i in range(5):
assert c[i] == i - 1
def test_subtract_constant(self):
from numpy import array
a = array(range(5))
- b = (a - 5).force()
+ b = a - 5
for i in range(5):
assert b[i] == i - 5
@@ -70,7 +67,6 @@
from numpy import array
a = array(range(5))
b = a * a
- b = b.force()
for i in range(5):
assert b[i] == i * i
@@ -78,14 +74,13 @@
from numpy import array
a = array(range(5))
b = a * 5
- b = b.force()
for i in range(5):
assert b[i] == i * 5
def test_div(self):
from numpy import array
a = array(range(1, 6))
- b = (a / a).force()
+ b = a / a
for i in range(5):
assert b[i] == 1
@@ -93,17 +88,25 @@
from numpy import array
a = array(range(5))
b = array([2, 2, 2, 2, 2])
- c = (a / b).force()
+ c = a / b
for i in range(5):
assert c[i] == i / 2.0
def test_div_constant(self):
from numpy import array
a = array(range(5))
- b = (a / 5.0).force()
+ b = a / 5.0
for i in range(5):
assert b[i] == i / 5.0
+ def test_auto_force(self):
+ from numpy import array
+ a = array(range(5))
+ b = a - 1
+ a[2] = 3
+ for i in range(5):
+ assert b[i] == i - 1
+
class AppTestNumpy(object):
def setup_class(cls):
py.test.skip("unimplemented")
From commits-noreply at bitbucket.org Thu May 5 01:18:04 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 01:18:04 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Don't recompile something that was
already forced.
Message-ID: <20110504231804.B8A892A202B@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43900:2cf217a6ce0d
Date: 2011-05-04 19:17 -0400
http://bitbucket.org/pypy/pypy/changeset/2cf217a6ce0d/
Log: Don't recompile something that was already forced.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -213,6 +213,9 @@
self.forced_result = None
def compile(self):
+ if self.forced_result is not None:
+ return self.forced_result.compile()
+
left_code = self.left.compile()
right_code = self.right.compile()
return left_code.merge(self.opcode, right_code)
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -7,10 +7,10 @@
class TestNumpyJIt(LLJitMixin):
def setup_class(cls):
cls.space = FakeSpace()
-
+
def test_add(self):
space = self.space
-
+
def f(i):
ar = SingleDimArray(i)
if i:
@@ -41,3 +41,22 @@
"setarrayitem_raw": 1, "int_add": 1,
"int_lt": 1, "guard_true": 1, "jump": 1})
assert result == f(5)
+
+ def test_already_forecd(self):
+ space = self.space
+
+ def f(i):
+ ar = SingleDimArray(i)
+ v1 = BinOp('a', ar, FloatWrapper(4.5))
+ v2 = BinOp('m', v1, FloatWrapper(4.5))
+ v1.force_if_needed()
+ return v2.force().storage[3]
+
+ result = self.meta_interp(f, [5], listops=True, backendopt=True)
+ # This is the sum of the ops for both loops, however if you remove the
+ # optimization then you end up with 2 float_adds, so we can still be
+ # sure it was optimized correctly.
+ self.check_loops({"getarrayitem_raw": 2, "float_mul": 1, "float_add": 1,
+ "setarrayitem_raw": 2, "int_add": 2,
+ "int_lt": 2, "guard_true": 2, "jump": 2})
+ assert result == f(5)
\ No newline at end of file
From commits-noreply at bitbucket.org Thu May 5 01:20:44 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 01:20:44 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Fix for forcing with this benchmark.
Message-ID: <20110504232044.7FF882A202B@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43901:281b07da091d
Date: 2011-05-04 19:20 -0400
http://bitbucket.org/pypy/pypy/changeset/281b07da091d/
Log: Fix for forcing with this benchmark.
diff --git a/pypy/module/micronumpy/bench/add.py b/pypy/module/micronumpy/bench/add.py
--- a/pypy/module/micronumpy/bench/add.py
+++ b/pypy/module/micronumpy/bench/add.py
@@ -4,7 +4,7 @@
def f():
a = numpy.zeros(10000000)
a = a + a + a + a + a
- if hasattr(a, 'force'):
- a.force()
+ # To ensure that the computation isn't totally optimized away.
+ a[0] = 3.0
f()
From commits-noreply at bitbucket.org Thu May 5 02:13:43 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 02:13:43 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Remove this file,
it's dead ATM. Fish it out of history if you want the one
function that would need to mostly be rewritten anyways.
Message-ID: <20110505001343.641662A202D@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43902:40189e8d428a
Date: 2011-05-04 20:13 -0400
http://bitbucket.org/pypy/pypy/changeset/40189e8d428a/
Log: Remove this file, it's dead ATM. Fish it out of history if you want
the one function that would need to mostly be rewritten anyways.
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -1,6 +1,7 @@
import py
from pypy.conftest import gettestobjspace
+
class AppTestNumpyLike(object):
def setup_class(cls):
cls.space = gettestobjspace(usemodules=('micronumpy',))
diff --git a/pypy/module/micronumpy/ufunc.py b/pypy/module/micronumpy/ufunc.py
deleted file mode 100644
--- a/pypy/module/micronumpy/ufunc.py
+++ /dev/null
@@ -1,21 +0,0 @@
-
-from numarray import NumArray
-from pypy.interpreter.baseobjspace import ObjSpace, W_Root
-from pypy.interpreter.error import OperationError
-
-def minimum(space, w_a, w_b):
- if not isinstance(w_a, NumArray) or not isinstance(w_b, NumArray):
- raise OperationError(space.w_TypeError,
- space.wrap("expecting NumArrat object"))
- if w_a.dim != w_b.dim:
- raise OperationError(space.w_ValueError,
- space.wrap("minimum of arrays of different length"))
- res = NumArray(space, w_a.dim, 'i')
- for i in range(len(w_a.storage)):
- one = w_a.storage[i]
- two = w_b.storage[i]
- if one < two:
- res.storage[i] = one
- else:
- res.storage[i] = two
- return space.wrap(res)
From commits-noreply at bitbucket.org Thu May 5 03:30:00 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 03:30:00 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Fixed the bounds check in getitem,
thanks to nightless_night for the patch.
Message-ID: <20110505013000.8D0BE2A2031@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43903:681ae61969d1
Date: 2011-05-04 21:29 -0400
http://bitbucket.org/pypy/pypy/changeset/681ae61969d1/
Log: Fixed the bounds check in getitem, thanks to nightless_night for the
patch.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -263,7 +263,7 @@
if item < 0:
raise operationerrfmt(space.w_TypeError,
'%d below zero', item)
- if item > self.size:
+ if item >= self.size:
raise operationerrfmt(space.w_TypeError,
'%d above array size', item)
return space.wrap(self.storage[item])
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -20,6 +20,13 @@
a = array(range(5))
assert a[3] == 3
+ def test_getitem(self):
+ from numpy import array
+ a = array(range(5))
+ raises(TypeError, "a[5]")
+ a = a + a
+ raises(TypeError, "a[5]")
+
def test_add(self):
from numpy import array
a = array(range(5))
From commits-noreply at bitbucket.org Thu May 5 03:47:12 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 03:47:12 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Fixed the exception raises in a
bound-error case.
Message-ID: <20110505014712.24C642A2031@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43904:bf69a764de41
Date: 2011-05-04 21:46 -0400
http://bitbucket.org/pypy/pypy/changeset/bf69a764de41/
Log: Fixed the exception raises in a bound-error case.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -260,12 +260,14 @@
@unwrap_spec(item=int)
def descr_getitem(self, space, item):
+ if item >= self.size:
+ raise operationerrfmt(space.w_IndexError,
+ '%d above array size', item)
if item < 0:
- raise operationerrfmt(space.w_TypeError,
+ item += self.size
+ if item < 0:
+ raise operationerrfmt(space.w_IndexError,
'%d below zero', item)
- if item >= self.size:
- raise operationerrfmt(space.w_TypeError,
- '%d above array size', item)
return space.wrap(self.storage[item])
@unwrap_spec(item=int, value=float)
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -23,9 +23,11 @@
def test_getitem(self):
from numpy import array
a = array(range(5))
- raises(TypeError, "a[5]")
+ raises(IndexError, "a[5]")
a = a + a
- raises(TypeError, "a[5]")
+ raises(IndexError, "a[5]")
+ assert a[-1] == 8
+ raises(IndexError, "a[-6]")
def test_add(self):
from numpy import array
From commits-noreply at bitbucket.org Thu May 5 03:52:55 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 03:52:55 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Fixed a typo.
Message-ID: <20110505015255.514C02A2031@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43905:235fc3e56531
Date: 2011-05-04 21:52 -0400
http://bitbucket.org/pypy/pypy/changeset/235fc3e56531/
Log: Fixed a typo.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -231,7 +231,7 @@
@unwrap_spec(item=int, value=float)
def descr_setitem(self, space, item, value):
- self.forced_if_needed()
+ self.force_if_needed()
self.invalidated()
return self.forced_result.descr_setitem(space, item, value)
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -117,6 +117,12 @@
for i in range(5):
assert b[i] == i - 1
+ a = array(range(5))
+ b = a + a
+ c = b + b
+ b[1] = 5
+ assert c[1] == 4
+
class AppTestNumpy(object):
def setup_class(cls):
py.test.skip("unimplemented")
From commits-noreply at bitbucket.org Thu May 5 04:08:17 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 04:08:17 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Fixed bound checks on setitem (patch
from nightless_night). Also a little housekeeping.
Message-ID: <20110505020817.3FE4436C205@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43906:7fb3818f9eae
Date: 2011-05-04 22:08 -0400
http://bitbucket.org/pypy/pypy/changeset/7fb3818f9eae/
Log: Fixed bound checks on setitem (patch from nightless_night). Also a
little housekeeping.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -258,8 +258,7 @@
def compile(self):
return Code('l', [self], [])
- @unwrap_spec(item=int)
- def descr_getitem(self, space, item):
+ def getindex(self, space, item):
if item >= self.size:
raise operationerrfmt(space.w_IndexError,
'%d above array size', item)
@@ -268,16 +267,16 @@
if item < 0:
raise operationerrfmt(space.w_IndexError,
'%d below zero', item)
+ return item
+
+ @unwrap_spec(item=int)
+ def descr_getitem(self, space, item):
+ item = self.getindex(space, item)
return space.wrap(self.storage[item])
@unwrap_spec(item=int, value=float)
def descr_setitem(self, space, item, value):
- if item < 0:
- raise operationerrfmt(space.w_TypeError,
- '%d below zero', item)
- if item > self.size:
- raise operationerrfmt(space.w_TypeError,
- '%d above array size', item)
+ item = self.getindex(space, item)
self.invalidated()
self.storage[item] = value
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -29,6 +29,14 @@
assert a[-1] == 8
raises(IndexError, "a[-6]")
+ def test_setitem(self):
+ from numpy import array
+ a = array(range(5))
+ a[-1] = 5.0
+ assert a[4] == 5.0
+ raises(IndexError, "a[5] = 0.0")
+ raises(IndexError, "a[-6] = 3.0")
+
def test_add(self):
from numpy import array
a = array(range(5))
From commits-noreply at bitbucket.org Thu May 5 04:31:27 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 04:31:27 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: Implemented len(). Patch from
nightless_night.
Message-ID: <20110505023127.8716A2A202D@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43907:9cd5a7f63042
Date: 2011-05-04 22:31 -0400
http://bitbucket.org/pypy/pypy/changeset/9cd5a7f63042/
Log: Implemented len(). Patch from nightless_night.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -224,6 +224,10 @@
if self.forced_result is None:
self.forced_result = self.force()
+ def descr_len(self, space):
+ self.force_if_needed()
+ return self.forced_result.descr_len(space)
+
@unwrap_spec(item=int)
def descr_getitem(self, space, item):
self.force_if_needed()
@@ -238,6 +242,7 @@
BinOp.typedef = TypeDef(
'Operation',
+ __len__ = interp2app(BinOp.descr_len),
__getitem__ = interp2app(BinOp.descr_getitem),
__setitem__ = interp2app(BinOp.descr_setitem),
@@ -269,6 +274,9 @@
'%d below zero', item)
return item
+ def descr_len(self, space):
+ return space.wrap(self.size)
+
@unwrap_spec(item=int)
def descr_getitem(self, space, item):
item = self.getindex(space, item)
@@ -300,8 +308,10 @@
SingleDimArray.typedef = TypeDef(
'numarray',
__new__ = interp2app(descr_new_numarray),
+ __len__ = interp2app(SingleDimArray.descr_len),
__getitem__ = interp2app(SingleDimArray.descr_getitem),
__setitem__ = interp2app(SingleDimArray.descr_setitem),
+
__add__ = interp2app(BaseArray.descr_add),
__sub__ = interp2app(BaseArray.descr_sub),
__mul__ = interp2app(BaseArray.descr_mul),
diff --git a/pypy/module/micronumpy/test/test_numpy.py b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -37,6 +37,12 @@
raises(IndexError, "a[5] = 0.0")
raises(IndexError, "a[-6] = 3.0")
+ def test_len(self):
+ from numpy import array
+ a = array(range(5))
+ assert len(a) == 5
+ assert len(a + a) == 5
+
def test_add(self):
from numpy import array
a = array(range(5))
From commits-noreply at bitbucket.org Thu May 5 08:53:58 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Thu, 5 May 2011 08:53:58 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: some tests
Message-ID: <20110505065358.1CB332A202D@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43908:29f4c6179f37
Date: 2011-05-05 07:58 +0200
http://bitbucket.org/pypy/pypy/changeset/29f4c6179f37/
Log: some tests
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2320,6 +2320,48 @@
return sa
assert self.meta_interp(f, [20, 1, 2]) == f(20, 1, 2)
+ def test_inlined_short_preamble_guard_needed_in_loop1(self):
+ class A(object):
+ def __init__(self, a):
+ self.a = a
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa',
+ 'a', 'b'])
+ def f(n, a, b):
+ sa = i = 0
+ while i < n:
+ myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a, b=b)
+ if a.a < 10:
+ sa += a.a
+ b.a = i
+ i += 1
+ return sa
+ def g(n):
+ return f(n, A(5), A(10))
+ assert self.meta_interp(g, [20]) == g(20)
+
+ def test_inlined_short_preamble_guard_needed_in_loop2(self):
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa',
+ 'a', 'b'])
+ def f(n):
+ sa = i = 0
+ a = b = []
+ while i < n:
+ myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a, b=b)
+ a = []
+ sa += i
+ i += 1
+ return sa
+ assert self.meta_interp(f, [20]) == f(20)
+
+
+
+ def test_varray_boxed(self):
+ myjitdriver = JitDriver(greens = [], reds = ['a'])
+ a = []
+ while True:
+ myjitdriver.jit_merge_point(a=a)
+ a = []
+
class TestOOtype(BasicTests, OOJitMixin):
def test_oohash(self):
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -1496,6 +1496,23 @@
"""
self.optimize_loop(ops, expected, preamble)
+ def test_varray_boxed(self):
+ ops = """
+ [p8]
+ p31 = new(descr=ssize)
+ setfield_gc(p31, 0, descr=adescr)
+ p33 = new_array(0, descr=arraydescr)
+ setfield_gc(p31, p33, descr=bdescr)
+ p35 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p35, p31, descr=valuedescr)
+ jump(p35)
+ """
+ expected = """
+ []
+ jump()
+ """
+ self.optimize_loop(ops, expected)
+
def test_varray_1(self):
ops = """
[i1]
From commits-noreply at bitbucket.org Thu May 5 08:53:59 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Thu, 5 May 2011 08:53:59 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: failing test (finaly!)
Message-ID: <20110505065359.750B02A202D@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43909:3e440fe69f02
Date: 2011-05-05 08:51 +0200
http://bitbucket.org/pypy/pypy/changeset/3e440fe69f02/
Log: failing test (finaly!)
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -1496,20 +1496,41 @@
"""
self.optimize_loop(ops, expected, preamble)
- def test_varray_boxed(self):
- ops = """
- [p8]
+ def test_varray_boxed1(self):
+ ops = """
+ [p0, p8]
+ p11 = getfield_gc(p0, descr=otherdescr)
+ guard_nonnull(p11) [p0, p8]
+ guard_class(p11, ConstClass(node_vtable2)) [p0, p8]
+ p14 = getfield_gc(p11, descr=otherdescr)
+ guard_isnull(p14) [p0, p8]
+ p18 = getfield_gc(ConstPtr(myptr), descr=otherdescr)
+ guard_isnull(p18) [p0, p8]
p31 = new(descr=ssize)
setfield_gc(p31, 0, descr=adescr)
p33 = new_array(0, descr=arraydescr)
setfield_gc(p31, p33, descr=bdescr)
p35 = new_with_vtable(ConstClass(node_vtable))
setfield_gc(p35, p31, descr=valuedescr)
- jump(p35)
- """
- expected = """
- []
- jump()
+ jump(p0, p35)
+ """
+ expected = """
+ [p0]
+ jump(p0)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_varray_boxed_simplified(self):
+ ops = """
+ [p0, p8]
+ p18 = getfield_gc(ConstPtr(myptr), descr=otherdescr)
+ guard_isnull(p18) [p0, p8]
+ p31 = new(descr=ssize)
+ jump(p0, p35)
+ """
+ expected = """
+ [p0]
+ jump(p0)
"""
self.optimize_loop(ops, expected)
From commits-noreply at bitbucket.org Thu May 5 08:54:01 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Thu, 5 May 2011 08:54:01 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: killed pointless tests
Message-ID: <20110505065401.6A88B2A202D@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43910:4a7204269642
Date: 2011-05-05 08:53 +0200
http://bitbucket.org/pypy/pypy/changeset/4a7204269642/
Log: killed pointless tests
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2339,29 +2339,6 @@
return f(n, A(5), A(10))
assert self.meta_interp(g, [20]) == g(20)
- def test_inlined_short_preamble_guard_needed_in_loop2(self):
- myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa',
- 'a', 'b'])
- def f(n):
- sa = i = 0
- a = b = []
- while i < n:
- myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a, b=b)
- a = []
- sa += i
- i += 1
- return sa
- assert self.meta_interp(f, [20]) == f(20)
-
-
-
- def test_varray_boxed(self):
- myjitdriver = JitDriver(greens = [], reds = ['a'])
- a = []
- while True:
- myjitdriver.jit_merge_point(a=a)
- a = []
-
class TestOOtype(BasicTests, OOJitMixin):
def test_oohash(self):
From commits-noreply at bitbucket.org Thu May 5 10:37:34 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Thu, 5 May 2011 10:37:34 +0200 (CEST)
Subject: [pypy-svn] pypy default: add a warning in case oprofile has been
explicitly enabled but it is not found
Message-ID: <20110505083734.B2AF92A202D@codespeak.net>
Author: Antonio Cuni
Branch:
Changeset: r43911:b693c615a51f
Date: 2011-05-05 10:36 +0200
http://bitbucket.org/pypy/pypy/changeset/b693c615a51f/
Log: add a warning in case oprofile has been explicitly enabled but it is
not found
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -1,3 +1,4 @@
+import py
from pypy.rpython.lltypesystem import lltype, llmemory, rffi
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.llinterp import LLInterpreter
@@ -10,6 +11,11 @@
from pypy.jit.backend.x86 import regloc
import sys
+from pypy.tool.ansi_print import ansi_log
+log = py.log.Producer('jitbackend')
+py.log.setconsumer('jitbackend', ansi_log)
+
+
class AbstractX86CPU(AbstractLLCPU):
debug = True
supports_floats = True
@@ -29,6 +35,8 @@
config = rtyper.annotator.translator.config
if config.translation.jit_profiler == "oprofile":
from pypy.jit.backend.x86 import oprofile
+ if not oprofile.OPROFILE_AVAILABLE:
+ log.WARNING('oprofile support was explicitly enabled, but oprofile headers seem not to be available')
profile_agent = oprofile.OProfileAgent()
self.profile_agent = profile_agent
From commits-noreply at bitbucket.org Thu May 5 10:37:37 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Thu, 5 May 2011 10:37:37 +0200 (CEST)
Subject: [pypy-svn] pypy default: merge heads
Message-ID: <20110505083737.39BE32A2033@codespeak.net>
Author: Antonio Cuni
Branch:
Changeset: r43912:7229a88389a6
Date: 2011-05-05 10:37 +0200
http://bitbucket.org/pypy/pypy/changeset/7229a88389a6/
Log: merge heads
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
@@ -43,8 +43,8 @@
class TestAnnotateTestCase:
- def setup_class(cls):
- cls.space = FlowObjSpace()
+ def setup_class(cls):
+ cls.space = FlowObjSpace()
def teardown_method(self, meth):
assert annmodel.s_Bool == annmodel.SomeBool()
@@ -263,7 +263,7 @@
getcdef = a.bookkeeper.getuniqueclassdef
assert getcdef(snippet.F).attrs.keys() == ['m']
assert getcdef(snippet.G).attrs.keys() == ['m2']
- assert getcdef(snippet.H).attrs.keys() == ['attr']
+ assert getcdef(snippet.H).attrs.keys() == ['attr']
assert getcdef(snippet.H).about_attribute('attr') == (
a.bookkeeper.immutablevalue(1))
@@ -390,34 +390,34 @@
def test_tuple_unpack_from_const_tuple_with_different_types(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.func_arg_unpack, [])
- assert isinstance(s, annmodel.SomeInteger)
- assert s.const == 3
+ assert isinstance(s, annmodel.SomeInteger)
+ assert s.const == 3
def test_pbc_attr_preserved_on_instance(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.preserve_pbc_attr_on_instance, [bool])
#a.simplify()
#a.translator.view()
- assert s == annmodel.SomeInteger(nonneg=True)
- #self.assertEquals(s.__class__, annmodel.SomeInteger)
+ assert s == annmodel.SomeInteger(nonneg=True)
+ #self.assertEquals(s.__class__, annmodel.SomeInteger)
def test_pbc_attr_preserved_on_instance_with_slots(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.preserve_pbc_attr_on_instance_with_slots,
[bool])
- assert s == annmodel.SomeInteger(nonneg=True)
-
- def test_is_and_knowntype_data(self):
+ assert s == annmodel.SomeInteger(nonneg=True)
+
+ def test_is_and_knowntype_data(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.is_and_knowntype, [str])
#a.simplify()
#a.translator.view()
assert s == a.bookkeeper.immutablevalue(None)
- def test_isinstance_and_knowntype_data(self):
+ def test_isinstance_and_knowntype_data(self):
a = self.RPythonAnnotator()
x = a.bookkeeper.immutablevalue(snippet.apbc)
- s = a.build_types(snippet.isinstance_and_knowntype, [x])
+ s = a.build_types(snippet.isinstance_and_knowntype, [x])
#a.simplify()
#a.translator.view()
assert s == x
@@ -434,8 +434,8 @@
# the annotator (it doesn't check that they operate property, though)
for example, methname, s_example in [
('', 'join', annmodel.SomeString()),
- ([], 'append', somelist()),
- ([], 'extend', somelist()),
+ ([], 'append', somelist()),
+ ([], 'extend', somelist()),
([], 'reverse', somelist()),
([], 'insert', somelist()),
([], 'pop', somelist()),
@@ -465,6 +465,13 @@
assert isinstance(s, annmodel.SomeList)
assert s.listdef.listitem.resized
+ def test_str_mul(self):
+ a = self.RPythonAnnotator()
+ def f(a_str):
+ return a_str * 3
+ s = a.build_types(f, [str])
+ assert isinstance(s, annmodel.SomeString)
+
def test_simple_slicing(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.simple_slice, [list])
@@ -474,7 +481,7 @@
a = self.RPythonAnnotator()
s = a.build_types(snippet.simple_iter, [list])
assert isinstance(s, annmodel.SomeIterator)
-
+
def test_simple_iter_next(self):
def f(x):
i = iter(range(x))
@@ -498,7 +505,7 @@
assert listitem(s).knowntype == tuple
assert listitem(s).items[0].knowntype == int
assert listitem(s).items[1].knowntype == str
-
+
def test_dict_copy(self):
a = self.RPythonAnnotator()
t = somedict(annmodel.SomeInteger(), annmodel.SomeInteger())
@@ -544,7 +551,7 @@
a = self.RPythonAnnotator()
s = a.build_types(snippet.dict_values, [])
assert isinstance(listitem(s), annmodel.SomeString)
-
+
def test_dict_values2(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.dict_values2, [])
@@ -570,19 +577,19 @@
assert isinstance(dictkey(s), annmodel.SomeString)
assert isinstance(dictvalue(s), annmodel.SomeInteger)
assert not dictvalue(s).nonneg
-
+
def test_exception_deduction(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.exception_deduction, [])
assert isinstance(s, annmodel.SomeInstance)
assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
-
+
def test_exception_deduction_we_are_dumb(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.exception_deduction_we_are_dumb, [])
assert isinstance(s, annmodel.SomeInstance)
assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
-
+
def test_nested_exception_deduction(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.nested_exception_deduction, [])
@@ -645,8 +652,8 @@
assert Rdef.attrs['r'].s_value.classdef == Rdef
assert Rdef.attrs['n'].s_value.knowntype == int
assert Rdef.attrs['m'].s_value.knowntype == int
-
-
+
+
def test_propagation_of_fresh_instances_through_attrs_rec_eo(self):
a = self.RPythonAnnotator()
s = a.build_types(snippet.make_eo, [int])
@@ -958,7 +965,7 @@
f1(1,2)
g(f2)
g(f3)
-
+
a = self.RPythonAnnotator()
s = a.build_types(h, [])
@@ -1022,7 +1029,7 @@
famA_m = mdescA_m.getcallfamily()
famC_m = mdescC_m.getcallfamily()
famB_n = mdescB_n.getcallfamily()
-
+
assert famA_m is famC_m
assert famB_n is not famA_m
@@ -1038,7 +1045,7 @@
gfCinit = graphof(a, C.__init__.im_func)
assert famCinit.calltables == {(1, (), False, False): [{mdescCinit.funcdesc: gfCinit}] }
-
+
def test_isinstance_usigned(self):
def f(x):
return isinstance(x, r_uint)
@@ -1085,7 +1092,7 @@
s = a.build_types(f, [])
C1df = a.bookkeeper.getuniqueclassdef(C1)
C2df = a.bookkeeper.getuniqueclassdef(C2)
-
+
assert s.items[0].classdef == C1df
assert s.items[1].classdef == C2df
@@ -1098,29 +1105,29 @@
assert a.binding(graph2.getreturnvar()).classdef == C2df
assert graph1 in a.translator.graphs
assert graph2 in a.translator.graphs
-
+
def test_specialcase_args(self):
class C1(object):
pass
-
+
class C2(object):
pass
-
+
def alloc(cls, cls2):
i = cls()
assert isinstance(i, cls)
j = cls2()
assert isinstance(j, cls2)
return i
-
+
def f():
alloc(C1, C1)
alloc(C1, C2)
alloc(C2, C1)
alloc(C2, C2)
-
+
alloc._annspecialcase_ = "specialize:arg(0,1)"
-
+
a = self.RPythonAnnotator()
C1df = a.bookkeeper.getuniqueclassdef(C1)
C2df = a.bookkeeper.getuniqueclassdef(C2)
@@ -1180,9 +1187,9 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [int, int])
-
+
executedesc = a.bookkeeper.getdesc(I.execute.im_func)
- assert len(executedesc._cache) == 2
+ assert len(executedesc._cache) == 2
assert len(executedesc._cache[(0, 'star', 2)].startblock.inputargs) == 4
assert len(executedesc._cache[(1, 'star', 3)].startblock.inputargs) == 5
@@ -1201,7 +1208,7 @@
s_item = listitem(s)
assert isinstance(s_item, annmodel.SomeInstance)
assert s_item.classdef is a.bookkeeper.getuniqueclassdef(T)
-
+
def test_assert_type_is_list_doesnt_lose_info(self):
class T(object):
pass
@@ -1254,7 +1261,7 @@
x = bool(l)
l.append(1)
return x, bool(l)
-
+
a = self.RPythonAnnotator()
s = a.build_types(f, [])
assert s.const == False
@@ -1264,7 +1271,7 @@
assert s.items[0].knowntype == bool and not s.items[0].is_constant()
assert s.items[1].knowntype == bool and not s.items[1].is_constant()
-
+
def test_empty_dict(self):
def f():
d = {}
@@ -1274,7 +1281,7 @@
x = bool(d)
d['a'] = 1
return x, bool(d)
-
+
a = self.RPythonAnnotator()
s = a.build_types(f, [])
assert s.const == False
@@ -1534,7 +1541,7 @@
def witness1(x):
pass
def witness2(x):
- pass
+ pass
def f(x):
if 0 < x:
witness1(x)
@@ -1543,15 +1550,15 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [annmodel.SomeInteger(unsigned=True)])
wg1 = graphof(a, witness1)
- wg2 = graphof(a, witness2)
+ wg2 = graphof(a, witness2)
assert a.binding(wg1.getargs()[0]).unsigned is True
- assert a.binding(wg2.getargs()[0]).unsigned is True
-
+ assert a.binding(wg2.getargs()[0]).unsigned is True
+
def test_general_nonneg_cleverness_is_gentle_with_unsigned(self):
def witness1(x):
pass
def witness2(x):
- pass
+ pass
def f(x):
if 0 < x:
witness1(x)
@@ -1560,7 +1567,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [annmodel.SomeInteger(knowntype=r_ulonglong)])
wg1 = graphof(a, witness1)
- wg2 = graphof(a, witness2)
+ wg2 = graphof(a, witness2)
assert a.binding(wg1.getargs()[0]).knowntype is r_ulonglong
assert a.binding(wg2.getargs()[0]).knowntype is r_ulonglong
@@ -1742,11 +1749,11 @@
assert s.const == "bool"
a = self.RPythonAnnotator()
s = a.build_types(f, [int])
- assert s.const == "int"
+ assert s.const == "int"
a = self.RPythonAnnotator()
s = a.build_types(f, [float])
- assert s.const == "dontknow"
-
+ assert s.const == "dontknow"
+
def test_hidden_method(self):
class Base:
def method(self):
@@ -1825,7 +1832,7 @@
s = a.build_types(f, [])
assert s.knowntype == bool
assert not s.is_constant()
-
+
def test_const_dict_and_none(self):
def g(d=None):
return d is None
@@ -1837,7 +1844,7 @@
s = a.build_types(f, [])
assert s.knowntype == bool
assert not s.is_constant()
-
+
def test_issubtype_and_const(self):
class A(object):
pass
@@ -1951,7 +1958,7 @@
a = annrpython.RPythonAnnotator()
from pypy.annotation import model as annmodel
- s_f = a.bookkeeper.immutablevalue(f)
+ s_f = a.bookkeeper.immutablevalue(f)
a.bookkeeper.emulate_pbc_call('f', s_f, [annmodel.SomeInteger(), annmodel.SomeInteger()])
a.complete()
@@ -1960,7 +1967,7 @@
someint = annmodel.SomeInteger()
- assert (fdesc.get_s_signatures((2,(),False,False))
+ assert (fdesc.get_s_signatures((2,(),False,False))
== [([someint,someint],someint)])
def test_emulated_pbc_call_callback(self):
@@ -1974,7 +1981,7 @@
def callb(ann, graph):
memo.append(annmodel.SomeInteger() == ann.binding(graph.getreturnvar()))
- s_f = a.bookkeeper.immutablevalue(f)
+ s_f = a.bookkeeper.immutablevalue(f)
s = a.bookkeeper.emulate_pbc_call('f', s_f, [annmodel.SomeInteger(), annmodel.SomeInteger()],
callback=callb)
assert s == annmodel.SomeImpossibleValue()
@@ -1996,7 +2003,7 @@
s = a.build_types(f, [])
assert isinstance(s, annmodel.SomeIterator)
assert s.variant == ('items',)
-
+
def test_non_none_and_none_with_isinstance(self):
class A(object):
pass
@@ -2230,7 +2237,7 @@
def f(i):
witness(None)
return witness(get(i))
-
+
a = self.RPythonAnnotator()
s = a.build_types(f, [int])
assert s.__class__ == annmodel.SomeObject
@@ -2284,8 +2291,8 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [])
assert isinstance(s.items[0], annmodel.SomeInteger)
- assert isinstance(s.items[1], annmodel.SomeChar)
- assert isinstance(s.items[2], annmodel.SomeChar)
+ assert isinstance(s.items[1], annmodel.SomeChar)
+ assert isinstance(s.items[2], annmodel.SomeChar)
def test___class___attribute(self):
class Base(object): pass
@@ -2344,7 +2351,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [bool])
assert s.knowntype == int
-
+
def f(x):
return -x
@@ -2394,7 +2401,7 @@
assert isinstance(s, annmodel.SomeInteger)
assert s.knowntype == inttype
assert s.unsigned == (inttype(-1) > 0)
-
+
for inttype in inttypes:
def f():
return inttype(0)
@@ -2493,11 +2500,11 @@
def test_helper_method_annotator(self):
def fun():
return 21
-
+
class A(object):
def helper(self):
return 42
-
+
a = self.RPythonAnnotator()
a.build_types(fun, [])
a.annotate_helper_method(A, "helper", [])
@@ -2794,7 +2801,7 @@
def c(x):
return int(x)
-
+
def g(a, x):
if x == -1:
a = None
@@ -2806,7 +2813,7 @@
x = x + .01
return a(x)
- #def fun(x):
+ #def fun(x):
a = self.RPythonAnnotator(policy=policy.AnnotatorPolicy())
s = a.build_types(g, [annmodel.SomeGenericCallable(
@@ -2845,7 +2852,7 @@
class B(A):
def meth(self):
return self
- class C(A):
+ class C(A):
def meth(self):
return self
@@ -2893,7 +2900,7 @@
i.x = x
a = self.RPythonAnnotator()
- py.test.raises(Exception, a.build_types, f, [])
+ py.test.raises(Exception, a.build_types, f, [])
class M:
@@ -2910,30 +2917,30 @@
self.l2 = []
c = C()
-
+
def f():
x = A()
x = hint(x, access_directly=True)
c.m.l.append(x)
a = self.RPythonAnnotator()
- py.test.raises(AssertionError, a.build_types, f, [])
+ py.test.raises(AssertionError, a.build_types, f, [])
def f():
x = A()
x = hint(x, access_directly=True)
c.m.d[None] = x
-
+
a = self.RPythonAnnotator()
- py.test.raises(AssertionError, a.build_types, f, [])
+ py.test.raises(AssertionError, a.build_types, f, [])
def f():
x = A()
x = hint(x, access_directly=True)
c.m.d[x] = None
-
+
a = self.RPythonAnnotator()
- py.test.raises(AssertionError, a.build_types, f, [])
+ py.test.raises(AssertionError, a.build_types, f, [])
def test_ctr_location(self):
from pypy.rlib.jit import hint
@@ -3026,7 +3033,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [])
- assert isinstance(s, annmodel.SomeUnicodeString)
+ assert isinstance(s, annmodel.SomeUnicodeString)
def test_unicode(self):
def g(n):
@@ -3091,7 +3098,7 @@
a = self.RPythonAnnotator()
s = a.build_types(f, [str])
assert isinstance(s, annmodel.SomeString)
-
+
def f(x):
return u'a'.replace(x, u'b')
@@ -3105,7 +3112,7 @@
if c == i:
return c
return 'x'
-
+
a = self.RPythonAnnotator()
s = a.build_types(f, [unicode, str])
assert isinstance(s, annmodel.SomeUnicodeCodePoint)
@@ -3113,22 +3120,22 @@
def test_strformatting_unicode(self):
def f(x):
return '%s' % unichr(x)
-
+
a = self.RPythonAnnotator()
py.test.raises(NotImplementedError, a.build_types, f, [int])
def f(x):
return '%s' % (unichr(x) * 3)
-
+
a = self.RPythonAnnotator()
py.test.raises(NotImplementedError, a.build_types, f, [int])
def f(x):
return '%s%s' % (1, unichr(x))
-
+
a = self.RPythonAnnotator()
py.test.raises(NotImplementedError, a.build_types, f, [int])
def f(x):
return '%s%s' % (1, unichr(x) * 15)
-
+
a = self.RPythonAnnotator()
py.test.raises(NotImplementedError, a.build_types, f, [int])
@@ -3197,7 +3204,7 @@
called.append(True)
assert not ann.listdef.listitem.mutated
ann.listdef.never_resize()
-
+
def f():
l = [1,2,3]
check_annotation(l, checker)
@@ -3213,7 +3220,7 @@
def test_listitem_no_mutating2(self):
from pypy.rlib.debug import make_sure_not_resized
-
+
def f():
return make_sure_not_resized([1,2,3])
@@ -3293,11 +3300,11 @@
return d1[x].meth()
d1[i+1] = A()
return 0
-
+
a = self.RPythonAnnotator()
s = a.build_types(g, [int, int])
assert s.knowntype is int
-
+
def f(x):
d0 = {}
if x in d0:
@@ -3476,7 +3483,7 @@
return total
constant_unsigned_five = r_uint(5)
-
+
class Freezing:
def _freeze_(self):
return True
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -286,6 +286,7 @@
while True:
extended_arg_count = 0
offset = 0
+ force_redo = False
# Calculate the code offset of each block.
for block in blocks:
block.offset = offset
@@ -313,7 +314,7 @@
instr.has_jump = False
# The size of the code changed,
# we have to trigger another pass
- extended_arg_count += 1
+ force_redo = True
continue
if absolute:
jump_arg = target.offset
@@ -322,7 +323,7 @@
instr.arg = jump_arg
if jump_arg > 0xFFFF:
extended_arg_count += 1
- if extended_arg_count == last_extended_arg_count:
+ if extended_arg_count == last_extended_arg_count and not force_redo:
break
else:
last_extended_arg_count = extended_arg_count
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -73,6 +73,10 @@
def error_test(self, source, exc_type):
py.test.raises(exc_type, self.simple_test, source, None, None)
+ def test_issue_713(self):
+ func = "def f(_=2): return (_ if _ else _) if False else _"
+ yield self.st, func, "f()", 2
+
def test_long_jump(self):
func = """def f(x):
y = 0
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -11,7 +11,7 @@
from pypy.objspace.std.listobject import W_ListObject
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.tupleobject import W_TupleObject
-from pypy.rlib.rstring import StringBuilder, string_repeat
+from pypy.rlib.rstring import StringBuilder
from pypy.interpreter.buffer import StringBuffer
from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
@@ -856,7 +856,7 @@
if len(input) == 1:
s = input[0] * mul
else:
- s = string_repeat(input, mul)
+ s = input * mul
# xxx support again space.config.objspace.std.withstrjoin?
return W_StringObject(s)
@@ -963,19 +963,20 @@
space.wrap("translation table must be 256 characters long"))
string = w_string._value
- chars = []
deletechars = space.str_w(w_deletechars)
if len(deletechars) == 0:
+ buf = StringBuilder(len(string))
for char in string:
- chars.append(table[ord(char)])
+ buf.append(table[ord(char)])
else:
+ buf = StringBuilder()
deletion_table = [False] * 256
for c in deletechars:
deletion_table[ord(c)] = True
for char in string:
if not deletion_table[ord(char)]:
- chars.append(table[ord(char)])
- return W_StringObject(''.join(chars))
+ buf.append(table[ord(char)])
+ return W_StringObject(buf.build())
def str_decode__String_ANY_ANY(space, w_string, w_encoding=None, w_errors=None):
from pypy.objspace.std.unicodetype import _get_encoding_and_errors, \
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -11,7 +11,7 @@
from pypy.objspace.std.tupleobject import W_TupleObject
from pypy.rlib.rarithmetic import intmask, ovfcheck
from pypy.rlib.objectmodel import compute_hash
-from pypy.rlib.rstring import UnicodeBuilder, string_repeat
+from pypy.rlib.rstring import UnicodeBuilder
from pypy.rlib.runicode import unicode_encode_unicode_escape
from pypy.module.unicodedata import unicodedb
from pypy.tool.sourcetools import func_with_new_name
@@ -278,7 +278,7 @@
if len(input) == 1:
result = input[0] * times
else:
- result = string_repeat(input, times)
+ result = input * times
return W_UnicodeObject(result)
def mul__ANY_Unicode(space, w_times, w_uni):
diff --git a/pypy/rlib/rstring.py b/pypy/rlib/rstring.py
--- a/pypy/rlib/rstring.py
+++ b/pypy/rlib/rstring.py
@@ -3,7 +3,6 @@
from pypy.annotation.model import SomeObject, SomeString, s_None,\
SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString
-from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.extregistry import ExtRegistryEntry
@@ -79,32 +78,6 @@
tp = unicode
-# XXX: This does log(mul) mallocs, the GCs probably make that efficient, but
-# some measurement should be done at some point.
-def string_repeat(s, mul):
- """Repeat a string or unicode. Note that this assumes that 'mul' > 0."""
- result = None
- factor = 1
- assert mul > 0
- try:
- ovfcheck(len(s) * mul)
- except OverflowError:
- raise MemoryError
-
- limit = mul >> 1
- while True:
- if mul & factor:
- if result is None:
- result = s
- else:
- result = s + result
- if factor > limit:
- break
- s += s
- factor *= 2
- return result
-string_repeat._annspecialcase_ = 'specialize:argtype(0)'
-
# ------------------------------------------------------------
# ----------------- implementation details -------------------
# ------------------------------------------------------------
@@ -159,7 +132,7 @@
def method_build(self):
return SomeUnicodeString()
-
+
def rtyper_makerepr(self, rtyper):
return rtyper.type_system.rbuilder.unicodebuilder_repr
@@ -170,7 +143,7 @@
if self.use_unicode:
return SomeUnicodeBuilder()
return SomeStringBuilder()
-
+
def specialize_call(self, hop):
return hop.r_result.rtyper_new(hop)
diff --git a/pypy/rlib/test/test_rstring.py b/pypy/rlib/test/test_rstring.py
--- a/pypy/rlib/test/test_rstring.py
+++ b/pypy/rlib/test/test_rstring.py
@@ -1,7 +1,6 @@
import sys
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit, \
- string_repeat
+from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit
def test_split():
@@ -43,7 +42,4 @@
assert s.getlength() == len('aabcb')
s.append_multiple_char(u'd', 4)
assert s.build() == 'aabcbdddd'
- assert isinstance(s.build(), unicode)
-
-def test_string_repeat():
- raises(MemoryError, string_repeat, "abc", sys.maxint)
+ assert isinstance(s.build(), unicode)
\ 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
@@ -5,6 +5,7 @@
from pypy.rlib.objectmodel import _hash_string, enforceargs
from pypy.rlib.debug import ll_assert
from pypy.rlib.jit import purefunction, we_are_jitted
+from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.robject import PyObjRepr, pyobj_repr
from pypy.rpython.rmodel import inputconst, IntegerRepr
from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
@@ -255,6 +256,27 @@
class LLHelpers(AbstractLLHelpers):
+ @purefunction
+ def ll_str_mul(s, times):
+ if times < 0:
+ times = 0
+ try:
+ size = ovfcheck(len(s.chars) * times)
+ except OverflowError:
+ raise MemoryError
+ newstr = s.malloc(size)
+ i = 0
+ if i < size:
+ s.copy_contents(s, newstr, 0, 0, len(s.chars))
+ i += len(s.chars)
+ while i < size:
+ if i <= size - i:
+ j = i
+ else:
+ j = size - i
+ s.copy_contents(newstr, newstr, 0, i, j)
+ i += j
+ return newstr
@purefunction
def ll_char_mul(ch, times):
diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -1,4 +1,5 @@
from pypy.tool.pairtype import pairtype
+from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.error import TyperError
from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
AbstractUniCharRepr, AbstractStringIteratorRepr,\
@@ -134,6 +135,19 @@
i+= 1
return buf.ll_build()
+ def ll_str_mul(s, times):
+ if times < 0:
+ times = 0
+ try:
+ size = ovfcheck(s.ll_strlen() * times)
+ except OverflowError:
+ raise MemoryError
+ buf = ootype.new(typeOf(s).builder)
+ buf.ll_allocate(size)
+ for i in xrange(times):
+ buf.ll_append(s)
+ return buf.ll_build()
+
def ll_streq(s1, s2):
if s1 is None:
return s2 is None
@@ -203,7 +217,7 @@
return s.ll_substring(start, s.ll_strlen() - start)
def ll_stringslice_startstop(s, start, stop):
- length = s.ll_strlen()
+ length = s.ll_strlen()
if stop > length:
stop = length
return s.ll_substring(start, stop-start)
@@ -265,7 +279,7 @@
def ll_float(ll_str):
return ootype.ooparse_float(ll_str)
-
+
# interface to build strings:
# x = ll_build_start(n)
# ll_build_push(x, next_string, 0)
@@ -300,7 +314,7 @@
c8 = hop.inputconst(ootype.Signed, 8)
c10 = hop.inputconst(ootype.Signed, 10)
c16 = hop.inputconst(ootype.Signed, 16)
- c_StringBuilder = hop.inputconst(ootype.Void, ootype.StringBuilder)
+ c_StringBuilder = hop.inputconst(ootype.Void, ootype.StringBuilder)
v_buf = hop.genop("new", [c_StringBuilder], resulttype=ootype.StringBuilder)
things = cls.parse_fmt_string(s)
@@ -334,7 +348,7 @@
hop.genop('oosend', [c_append, v_buf, vchunk], resulttype=ootype.Void)
hop.exception_cannot_occur() # to ignore the ZeroDivisionError of '%'
- return hop.genop('oosend', [c_build, v_buf], resulttype=ootype.String)
+ return hop.genop('oosend', [c_build, v_buf], resulttype=ootype.String)
do_stringformat = classmethod(do_stringformat)
@@ -399,7 +413,7 @@
return iter
def ll_strnext(iter):
- string = iter.string
+ string = iter.string
index = iter.index
if index >= string.ll_strlen():
raise StopIteration
diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -34,7 +34,7 @@
class __extend__(annmodel.SomeUnicodeString):
def rtyper_makerepr(self, rtyper):
return rtyper.type_system.rstr.unicode_repr
-
+
def rtyper_makekey(self):
return self.__class__,
@@ -164,7 +164,7 @@
v_str, = hop.inputargs(string_repr)
hop.exception_cannot_occur()
return hop.gendirectcall(self.ll.ll_upper, v_str)
-
+
def rtype_method_lower(self, hop):
string_repr = hop.args_r[0].repr
v_str, = hop.inputargs(string_repr)
@@ -361,6 +361,17 @@
rtype_getitem_idx_key = rtype_getitem_idx
+ def rtype_mul((r_str, r_int), hop):
+ str_repr = r_str.repr
+ v_str, v_int = hop.inputargs(str_repr, Signed)
+ return hop.gendirectcall(r_str.ll.ll_str_mul, v_str, v_int)
+ rtype_inplace_mul = rtype_mul
+
+class __extend__(pairtype(IntegerRepr, AbstractStringRepr)):
+ def rtype_mul((r_int, r_str), hop):
+ return pair(r_str, r_int).rtype_mul(hop)
+ rtype_inplace_mul = rtype_mul
+
class __extend__(AbstractStringRepr):
@@ -384,7 +395,7 @@
def rtype_eq((r_str1, r_str2), hop):
v_str1, v_str2 = hop.inputargs(r_str1.repr, r_str2.repr)
return hop.gendirectcall(r_str1.ll.ll_streq, v_str1, v_str2)
-
+
def rtype_ne((r_str1, r_str2), hop):
v_str1, v_str2 = hop.inputargs(r_str1.repr, r_str2.repr)
vres = hop.gendirectcall(r_str1.ll.ll_streq, v_str1, v_str2)
@@ -465,7 +476,7 @@
return value
def get_ll_eq_function(self):
- return None
+ return None
def get_ll_hash_function(self):
return self.ll.ll_char_hash
@@ -505,7 +516,7 @@
class __extend__(pairtype(AbstractCharRepr, IntegerRepr),
pairtype(AbstractUniCharRepr, IntegerRepr)):
-
+
def rtype_mul((r_chr, r_int), hop):
char_repr = r_chr.char_repr
v_char, v_int = hop.inputargs(char_repr, Signed)
@@ -545,7 +556,7 @@
return value
def get_ll_eq_function(self):
- return None
+ return None
def get_ll_hash_function(self):
return self.ll.ll_unichar_hash
diff --git a/pypy/rpython/test/test_rstr.py b/pypy/rpython/test/test_rstr.py
--- a/pypy/rpython/test/test_rstr.py
+++ b/pypy/rpython/test/test_rstr.py
@@ -88,7 +88,7 @@
for i in range(3):
res = self.interpret(fn, [i])
assert res is True
-
+
def test_char_constant(self):
const = self.const
def fn(s):
@@ -141,6 +141,16 @@
res = self.interpret(fn, [const('5'), 3])
assert res == 5551
+ def test_str_mul(self):
+ const = self.const
+ def fn(i, mul):
+ s = ["", "a", "aba"][i]
+ return s * mul
+ for i in xrange(3):
+ for m in [0, 1, 4]:
+ res = self.interpret(fn, [i, m])
+ assert self.ll_to_string(res) == fn(i, m)
+
def test_is_none(self):
const = self.const
def fn(i):
@@ -295,7 +305,7 @@
for i, expected in enumerate([0, 1110, 2220, 3330, -1110, -1110]):
res = self.interpret(f, [i])
assert res == expected
-
+
def test_rfind(self):
const = self.const
def fn():
@@ -531,7 +541,7 @@
assert res.find('>, much nicer than , much nicer than
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43913:90bf45a5abc9
Date: 2011-05-05 11:07 +0200
http://bitbucket.org/pypy/pypy/changeset/90bf45a5abc9/
Log: ensure all surviving values are placed in optimizer.values
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
@@ -379,6 +379,11 @@
if bool_box:
new.bool_boxes[value] = None
+ for value in valuemap.values():
+ box = value.get_key_box()
+ if box not in new.values:
+ new.values[box] = value
+
return new
def produce_potential_short_preamble_ops(self, potential_ops):
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -162,7 +162,7 @@
virtual_state = modifier.get_virtual_state(jump_args)
values = [self.getvalue(arg) for arg in jump_args]
inputargs = virtual_state.make_inputargs(values)
-
+
sb = self.optimizer.produce_short_preamble_ops(inputargs)
self.short_boxes = sb
preamble_optimizer = self.optimizer
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -1526,6 +1526,8 @@
p18 = getfield_gc(ConstPtr(myptr), descr=otherdescr)
guard_isnull(p18) [p0, p8]
p31 = new(descr=ssize)
+ p35 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p35, p31, descr=valuedescr)
jump(p0, p35)
"""
expected = """
@@ -1533,6 +1535,22 @@
jump(p0)
"""
self.optimize_loop(ops, expected)
+
+ def test_varray_boxed_noconst(self):
+ ops = """
+ [p0, p8, p18, p19]
+ guard_isnull(p18) [p0, p8]
+ p31 = new(descr=ssize)
+ p35 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p35, p31, descr=valuedescr)
+ jump(p0, p35, p19, p18)
+ """
+ expected = """
+ [p0, p19]
+ guard_isnull(p19) [p0]
+ jump(p0, NULL)
+ """
+ self.optimize_loop(ops, expected)
def test_varray_1(self):
ops = """
From commits-noreply at bitbucket.org Thu May 5 13:03:46 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Thu, 5 May 2011 13:03:46 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: initiate interned_refs using
the original ConstantValues and make sure they are placed
in optimizer.values aswell
Message-ID: <20110505110346.3150B2A202B@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43915:5e359f5767de
Date: 2011-05-05 12:48 +0200
http://bitbucket.org/pypy/pypy/changeset/5e359f5767de/
Log: initiate interned_refs using the original ConstantValues and make
sure they are placed in optimizer.values aswell
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
@@ -356,10 +356,12 @@
for o in self.optimizations]
new.set_optimizations(optimizations)
- for value, box in self.interned_refs.items():
- if box in short_boxes:
- new.interned_refs[value] = box
-
+ for ref, box in self.interned_refs.items():
+ value = self.getvalue(box)
+ if isinstance(value, ConstantValue): # These are the only values surviving without being cloned
+ new.interned_refs[ref] = box
+ new.values[box] = value
+
new.pure_operations = args_dict()
for key, op in self.pure_operations.items():
if op.result in short_boxes:
From commits-noreply at bitbucket.org Thu May 5 13:03:47 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Thu, 5 May 2011 13:03:47 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: setfields no longer cached
across loop boundaries
Message-ID: <20110505110347.808662A202B@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43916:c278afb798ad
Date: 2011-05-05 13:00 +0200
http://bitbucket.org/pypy/pypy/changeset/c278afb798ad/
Log: setfields no longer cached across loop boundaries
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
@@ -196,8 +196,8 @@
return xy.inst_x
res = self.meta_interp(f, [20])
assert res == 134
- self.check_loops(getfield_gc=0, setfield_gc=1)
- self.check_loops(getfield_gc=1, setfield_gc=2, everywhere=True)
+ self.check_loops(getfield_gc=1, setfield_gc=1)
+ self.check_loops(getfield_gc=2, setfield_gc=2, everywhere=True)
# ------------------------------
From commits-noreply at bitbucket.org Thu May 5 17:13:51 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 17:13:51 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: Started on a follow up about numpy.
Message-ID: <20110505151351.0AB5D2A202D@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3565:0d31cd26248e
Date: 2011-05-05 11:13 -0400
http://bitbucket.org/pypy/extradoc/changeset/0d31cd26248e/
Log: Started on a follow up about numpy.
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
new file mode 100644
--- /dev/null
+++ b/blog/draft/numpy_followup.rst
@@ -0,0 +1,75 @@
+NumPy Follow Up
+===============
+
+Hi everyone. Since yesterday's blow post we got a ton of feedback, so I want
+to clarify a few things, as well as share some of the progress we've made, in
+only the 24 hours since the post.
+
+Reusing the original NumPy
+--------------------------
+
+First, a lot of people seem to think we should be reusing the original NumPy, via CPyExt (our CPython C-API compatibility layer). This isn't feasible for a few reasons:
+
+ 1) CPyExt is slow, and always will be slow. It has to emulate far too many
+ details of the CPython object model that don't exist on PyPy. Since people
+ using NumPy primarily for speed this would mean we could have a working
+ NumPy, but no one would want to use it.
+ 2) NumPy uses many obscure documented and undocumented details of the CPython
+ C-API. Emulating these is often difficult or impossible (e.g. we can't fix
+ accessing a struct field, as there's no function call for us to intercept).
+ 3) It's not much fun. Frankly, working on CPyExt, debugging the crashes, and
+ everything else that goes with it is not terribly fun, especially when you
+ know that the end result will be slow. We've demonstrated we can build a
+ much faster NumPy, in a way that's more fun, and given the people working
+ on this our volunteers, that's important to keep us motivated.
+
+C bindings vs. CPython C-API
+----------------------------
+
+There are two issues on C code, one has a very nice story, and the other not so
+much. First is the case of arbitrary C-code that isn't Python related, things
+like `libsqlite`, `libbz2`, or any random C shared library on your system. PyPy
+will quite happily call into these, and once we merge the `jittypes2` branch
+it'll even be smoking fast. The right way to do this binding is using the
+`ctypes` library, which every implementation of Python supports. On the other
+hand there is the CPython C-extension API. This is a very specific API which
+CPython exposes, and PyPy tries to emulate. It will never be fast, because
+there is far too much overhead in all the emulation that needs to be done. The
+correct solution for C-extensions is: if they are written for speed, rewrite
+them in pure-Python, it's our goal to obliterate the need for C for speed, as
+much as possible, if PyPy alone isn't fast enough then it might make sense to
+split your C-extension into 2 parts, one which doesn't touch the CPython C-API
+and thus can be loaded with `ctypes` and called from PyPy, and another which
+does the interfacing with Python for CPython (where it will be faster). There
+are also libraries written in C to interface with existing C codebases, but for
+whom performance is not the largest goal, for these the right solution is to
+try using CPyExt, and if it works that's great, but if it fails the solution
+will be to rewrite using `ctypes`, where it will work on all Python VMs, not
+just CPython. And finally there are rare cases where rewriting in RPython makes
+more sense, NumPy is one of the few examples of these because we need to be
+able to give the JIT hints on how to appropriately vectorize all of the
+operations on an array.
+
+Progress
+--------
+
+On a more positive note, since we wrote the last post we've had several new
+contributors, and I'd like to share some of the improvements that have been
+made to NumPy by them, I've only included patches from people totally new to
+PyPy:
+
+ * nightless_night contributed: An implementation of `__len__`, fixed bounds
+ checks on `__getitem__` and `__setitem__`.
+ * brentp contributed: Subtraction and division on NumPy arrays.
+ * MostAwesomeDude contributed: Multiplication on NumPy arrays.
+ * hodgestar contributed: Binary operations between floats and NumPy arrays.
+
+Those last two were technically an outstanding branch we finally merged, but
+hopefully you get the picture. In addition there was some exciting work done by
+regular PyPy contributors. I hope it's clear that there's a place to jump in
+for people with any level of PyPy familiarity. If you're interested in
+contributing please stop by #pypy on irc.freenode.net, the
+`pypy-dev `_ mailing list, or
+send us pull requests on `bitbucket `_.
+
+Alex
\ No newline at end of file
From commits-noreply at bitbucket.org Thu May 5 17:32:32 2011
From: commits-noreply at bitbucket.org (antocuni)
Date: Thu, 5 May 2011 17:32:32 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: review the blog post
Message-ID: <20110505153232.D9034282B58@codespeak.net>
Author: Antonio Cuni
Branch: extradoc
Changeset: r3566:a12bfab04d7f
Date: 2011-05-05 17:32 +0200
http://bitbucket.org/pypy/extradoc/changeset/a12bfab04d7f/
Log: review the blog post
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -1,23 +1,28 @@
NumPy Follow Up
===============
-Hi everyone. Since yesterday's blow post we got a ton of feedback, so I want
+Hi everyone. Since yesterday's blow post we got a ton of feedback, so we want
to clarify a few things, as well as share some of the progress we've made, in
only the 24 hours since the post.
Reusing the original NumPy
--------------------------
-First, a lot of people seem to think we should be reusing the original NumPy, via CPyExt (our CPython C-API compatibility layer). This isn't feasible for a few reasons:
+First, a lot of people asked why we cannot just reuse the original NumPy
+through ``cpyext``, our CPython C-API compatibility layer). We believe this
+is not the best approach, for a few reasons:
- 1) CPyExt is slow, and always will be slow. It has to emulate far too many
- details of the CPython object model that don't exist on PyPy. Since people
- using NumPy primarily for speed this would mean we could have a working
- NumPy, but no one would want to use it.
+ 1) ``cpyext`` is slow, and always will be slow. It has to emulate far too many
+ details of the CPython object model that don't exist on PyPy (e.g., reference counting). Since people
+ are using NumPy primarily for speed this would mean that even if we could have a working
+ NumPy, no one would want to use it. Also, as soon as the execution crosses the ``cpyext``
+ boundary, it becomes invisible to the JIT.
+
2) NumPy uses many obscure documented and undocumented details of the CPython
C-API. Emulating these is often difficult or impossible (e.g. we can't fix
accessing a struct field, as there's no function call for us to intercept).
- 3) It's not much fun. Frankly, working on CPyExt, debugging the crashes, and
+
+ 3) It's not much fun. Frankly, working on ``cpyext``, debugging the crashes, and
everything else that goes with it is not terribly fun, especially when you
know that the end result will be slow. We've demonstrated we can build a
much faster NumPy, in a way that's more fun, and given the people working
@@ -29,23 +34,35 @@
There are two issues on C code, one has a very nice story, and the other not so
much. First is the case of arbitrary C-code that isn't Python related, things
like `libsqlite`, `libbz2`, or any random C shared library on your system. PyPy
-will quite happily call into these, and once we merge the `jittypes2` branch
-it'll even be smoking fast. The right way to do this binding is using the
-`ctypes` library, which every implementation of Python supports. On the other
+will quite happily call into these, and bindings can be developed either at the
+RPython level (using ``rffi``) or in pure Python, using `ctypes`. Writing bindings
+with `ctypes` has the advantage that they can run on every alternative Python
+implementation, such as Jython and IronPython. Moreover, once we merge the `jittypes2` branch
+`ctypes` call will even be smoking fast.
+
+On the other
hand there is the CPython C-extension API. This is a very specific API which
CPython exposes, and PyPy tries to emulate. It will never be fast, because
-there is far too much overhead in all the emulation that needs to be done. The
-correct solution for C-extensions is: if they are written for speed, rewrite
-them in pure-Python, it's our goal to obliterate the need for C for speed, as
-much as possible, if PyPy alone isn't fast enough then it might make sense to
+there is far too much overhead in all the emulation that needs to be done.
+
+One of the reasons people write C extension is speed. Often, with PyPy you
+can just forget about C, write everything in pure python and let the JIT to do
+its magic.
+
+In case the PyPy JIT alone isn't fast enough then it might make sense to
split your C-extension into 2 parts, one which doesn't touch the CPython C-API
and thus can be loaded with `ctypes` and called from PyPy, and another which
-does the interfacing with Python for CPython (where it will be faster). There
+does the interfacing with Python for CPython (where it will be faster).
+
+There
are also libraries written in C to interface with existing C codebases, but for
whom performance is not the largest goal, for these the right solution is to
try using CPyExt, and if it works that's great, but if it fails the solution
will be to rewrite using `ctypes`, where it will work on all Python VMs, not
-just CPython. And finally there are rare cases where rewriting in RPython makes
+just CPython.
+
+
+And finally there are rare cases where rewriting in RPython makes
more sense, NumPy is one of the few examples of these because we need to be
able to give the JIT hints on how to appropriately vectorize all of the
operations on an array.
@@ -53,10 +70,9 @@
Progress
--------
-On a more positive note, since we wrote the last post we've had several new
-contributors, and I'd like to share some of the improvements that have been
-made to NumPy by them, I've only included patches from people totally new to
-PyPy:
+On a more positive note, after we published the `last post`_, several new people
+came and contributed improvements to the numpy-exp branch.
+We would like to thank all of them:
* nightless_night contributed: An implementation of `__len__`, fixed bounds
checks on `__getitem__` and `__setitem__`.
@@ -72,4 +88,4 @@
`pypy-dev `_ mailing list, or
send us pull requests on `bitbucket `_.
-Alex
\ No newline at end of file
+Alex
From commits-noreply at bitbucket.org Thu May 5 17:38:35 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 17:38:35 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: some small cleanups (and some reflow
for readability)
Message-ID: <20110505153835.7338336C053@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3567:721f0a89a9be
Date: 2011-05-05 11:38 -0400
http://bitbucket.org/pypy/extradoc/changeset/721f0a89a9be/
Log: some small cleanups (and some reflow for readability)
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -1,7 +1,7 @@
NumPy Follow Up
===============
-Hi everyone. Since yesterday's blow post we got a ton of feedback, so we want
+Hi everyone. Since yesterday's blog post we got a ton of feedback, so we want
to clarify a few things, as well as share some of the progress we've made, in
only the 24 hours since the post.
@@ -9,23 +9,24 @@
--------------------------
First, a lot of people asked why we cannot just reuse the original NumPy
-through ``cpyext``, our CPython C-API compatibility layer). We believe this
-is not the best approach, for a few reasons:
+through ``cpyext``, our CPython C-API compatibility layer. We believe this is
+not the best approach, for a few reasons:
1) ``cpyext`` is slow, and always will be slow. It has to emulate far too many
- details of the CPython object model that don't exist on PyPy (e.g., reference counting). Since people
- are using NumPy primarily for speed this would mean that even if we could have a working
- NumPy, no one would want to use it. Also, as soon as the execution crosses the ``cpyext``
- boundary, it becomes invisible to the JIT.
+ details of the CPython object model that don't exist on PyPy (e.g.,
+ reference counting). Since people are using NumPy primarily for speed this
+ would mean that even if we could have a working NumPy, no one would want to
+ use it. Also, as soon as the execution crosses the ``cpyext`` boundary, it
+ becomes invisible to the JIT.
2) NumPy uses many obscure documented and undocumented details of the CPython
C-API. Emulating these is often difficult or impossible (e.g. we can't fix
accessing a struct field, as there's no function call for us to intercept).
- 3) It's not much fun. Frankly, working on ``cpyext``, debugging the crashes, and
- everything else that goes with it is not terribly fun, especially when you
- know that the end result will be slow. We've demonstrated we can build a
- much faster NumPy, in a way that's more fun, and given the people working
+ 3) It's not much fun. Frankly, working on ``cpyext``, debugging the crashes,
+ and everything else that goes with it is not terribly fun, especially when
+ you know that the end result will be slow. We've demonstrated we can build
+ a much faster NumPy, in a way that's more fun, and given the people working
on this our volunteers, that's important to keep us motivated.
C bindings vs. CPython C-API
@@ -33,39 +34,39 @@
There are two issues on C code, one has a very nice story, and the other not so
much. First is the case of arbitrary C-code that isn't Python related, things
-like `libsqlite`, `libbz2`, or any random C shared library on your system. PyPy
-will quite happily call into these, and bindings can be developed either at the
-RPython level (using ``rffi``) or in pure Python, using `ctypes`. Writing bindings
-with `ctypes` has the advantage that they can run on every alternative Python
-implementation, such as Jython and IronPython. Moreover, once we merge the `jittypes2` branch
-`ctypes` call will even be smoking fast.
+like ``libsqlite``, ``libbz2``, or any random C shared library on your system.
+PyPy will quite happily call into these, and bindings can be developed either
+at the RPython level (using ``rffi``) or in pure Python, using ``ctypes``.
+Writing bindings with ``ctypes`` has the advantage that they can run on every
+alternative Python implementation, such as Jython and IronPython. Moreover,
+once we merge the ``jittypes2`` branch ``ctypes`` calls will even be smoking
+fast.
-On the other
-hand there is the CPython C-extension API. This is a very specific API which
-CPython exposes, and PyPy tries to emulate. It will never be fast, because
-there is far too much overhead in all the emulation that needs to be done.
+On the other hand there is the CPython C-extension API. This is a very specific
+API which CPython exposes, and PyPy tries to emulate. It will never be fast,
+because there is far too much overhead in all the emulation that needs to be
+done.
-One of the reasons people write C extension is speed. Often, with PyPy you
-can just forget about C, write everything in pure python and let the JIT to do
-its magic.
+One of the reasons people write C extension is speed. Often, with PyPy you can
+just forget about C, write everything in pure python and let the JIT to do its
+magic.
-In case the PyPy JIT alone isn't fast enough then it might make sense to
-split your C-extension into 2 parts, one which doesn't touch the CPython C-API
-and thus can be loaded with `ctypes` and called from PyPy, and another which
-does the interfacing with Python for CPython (where it will be faster).
+In case the PyPy JIT alone isn't fast enough then it might make sense to split
+your C-extension into 2 parts, one which doesn't touch the CPython C-API and
+thus can be loaded with ``ctypes`` and called from PyPy, and another which does
+the interfacing with Python for CPython (where it will be faster).
-There
-are also libraries written in C to interface with existing C codebases, but for
-whom performance is not the largest goal, for these the right solution is to
-try using CPyExt, and if it works that's great, but if it fails the solution
-will be to rewrite using `ctypes`, where it will work on all Python VMs, not
-just CPython.
+There are also libraries written in C to interface with existing C codebases,
+but for whom performance is not the largest goal, for these the right solution
+is to try using CPyExt, and if it works that's great, but if it fails the
+solution will be to rewrite using `ctypes`, where it will work on all Python
+VMs, not just CPython.
-And finally there are rare cases where rewriting in RPython makes
-more sense, NumPy is one of the few examples of these because we need to be
-able to give the JIT hints on how to appropriately vectorize all of the
-operations on an array.
+And finally there are rare cases where rewriting in RPython makes more sense,
+NumPy is one of the few examples of these because we need to be able to give
+the JIT hints on how to appropriately vectorize all of the operations on an
+array.
Progress
--------
From commits-noreply at bitbucket.org Thu May 5 17:38:52 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 17:38:52 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: more rst
Message-ID: <20110505153852.BADBF282B58@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3568:3926a636e810
Date: 2011-05-05 11:38 -0400
http://bitbucket.org/pypy/extradoc/changeset/3926a636e810/
Log: more rst
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -75,8 +75,8 @@
came and contributed improvements to the numpy-exp branch.
We would like to thank all of them:
- * nightless_night contributed: An implementation of `__len__`, fixed bounds
- checks on `__getitem__` and `__setitem__`.
+ * nightless_night contributed: An implementation of ``__len__``, fixed bounds
+ checks on ``__getitem__`` and ``__setitem__``.
* brentp contributed: Subtraction and division on NumPy arrays.
* MostAwesomeDude contributed: Multiplication on NumPy arrays.
* hodgestar contributed: Binary operations between floats and NumPy arrays.
From commits-noreply at bitbucket.org Thu May 5 19:03:54 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Thu, 5 May 2011 19:03:54 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: few small clarifications,
good otherwise
Message-ID: <20110505170354.C1B61282B58@codespeak.net>
Author: Maciej Fijalkowski
Branch: extradoc
Changeset: r3569:84b26c304309
Date: 2011-05-05 19:03 +0200
http://bitbucket.org/pypy/extradoc/changeset/84b26c304309/
Log: few small clarifications, good otherwise
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -17,7 +17,8 @@
reference counting). Since people are using NumPy primarily for speed this
would mean that even if we could have a working NumPy, no one would want to
use it. Also, as soon as the execution crosses the ``cpyext`` boundary, it
- becomes invisible to the JIT.
+ becomes invisible to the JIT, which means the JIT has to assume the worst
+ and deoptimize stuff away.
2) NumPy uses many obscure documented and undocumented details of the CPython
C-API. Emulating these is often difficult or impossible (e.g. we can't fix
@@ -27,7 +28,7 @@
and everything else that goes with it is not terribly fun, especially when
you know that the end result will be slow. We've demonstrated we can build
a much faster NumPy, in a way that's more fun, and given the people working
- on this our volunteers, that's important to keep us motivated.
+ on this are volunteers, that's important to keep us motivated.
C bindings vs. CPython C-API
----------------------------
@@ -51,7 +52,8 @@
just forget about C, write everything in pure python and let the JIT to do its
magic.
-In case the PyPy JIT alone isn't fast enough then it might make sense to split
+In case the PyPy JIT alone isn't fast enough, or you just want to
+use an existing C code then it might make sense to split
your C-extension into 2 parts, one which doesn't touch the CPython C-API and
thus can be loaded with ``ctypes`` and called from PyPy, and another which does
the interfacing with Python for CPython (where it will be faster).
From commits-noreply at bitbucket.org Thu May 5 19:52:06 2011
From: commits-noreply at bitbucket.org (lac)
Date: Thu, 5 May 2011 19:52:06 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: Add 2 XXX and minor copyediting
Message-ID: <20110505175206.EB4332A202D@codespeak.net>
Author: Laura Creighton
Branch: extradoc
Changeset: r3570:60d9fc809fd3
Date: 2011-05-05 19:51 +0200
http://bitbucket.org/pypy/extradoc/changeset/60d9fc809fd3/
Log: Add 2 XXX and minor copyediting
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -8,7 +8,7 @@
Reusing the original NumPy
--------------------------
-First, a lot of people asked why we cannot just reuse the original NumPy
+First, a lot of people have asked why we cannot just reuse the original NumPy
through ``cpyext``, our CPython C-API compatibility layer. We believe this is
not the best approach, for a few reasons:
@@ -27,8 +27,8 @@
3) It's not much fun. Frankly, working on ``cpyext``, debugging the crashes,
and everything else that goes with it is not terribly fun, especially when
you know that the end result will be slow. We've demonstrated we can build
- a much faster NumPy, in a way that's more fun, and given the people working
- on this are volunteers, that's important to keep us motivated.
+ a much faster NumPy, in a way that's more fun, and given that the people
+ working on this are volunteers, it's important to keep us motivated.
C bindings vs. CPython C-API
----------------------------
@@ -48,16 +48,18 @@
because there is far too much overhead in all the emulation that needs to be
done.
-One of the reasons people write C extension is speed. Often, with PyPy you can
+One of the reasons people write C extensions is for speed. Often, with PyPy
+you can
just forget about C, write everything in pure python and let the JIT to do its
magic.
In case the PyPy JIT alone isn't fast enough, or you just want to
-use an existing C code then it might make sense to split
+use existing C code then it might make sense to split
your C-extension into 2 parts, one which doesn't touch the CPython C-API and
thus can be loaded with ``ctypes`` and called from PyPy, and another which does
the interfacing with Python for CPython (where it will be faster).
+XXX I find this pararagraph unclear.
There are also libraries written in C to interface with existing C codebases,
but for whom performance is not the largest goal, for these the right solution
is to try using CPyExt, and if it works that's great, but if it fails the
@@ -68,7 +70,9 @@
And finally there are rare cases where rewriting in RPython makes more sense,
NumPy is one of the few examples of these because we need to be able to give
the JIT hints on how to appropriately vectorize all of the operations on an
-array.
+array. XXX Why? How can you recognize a library that should be rewritten
+in RPython compared to one that shouldn't? Should this be done for all
+speed critical libraries, or just certain ones, and if the latter, which?
Progress
--------
From commits-noreply at bitbucket.org Thu May 5 22:29:05 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 22:29:05 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: try to fix some xxx
Message-ID: <20110505202905.14E56282B58@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3571:10d1e77b1a3f
Date: 2011-05-05 16:28 -0400
http://bitbucket.org/pypy/extradoc/changeset/10d1e77b1a3f/
Log: try to fix some xxx
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -48,10 +48,9 @@
because there is far too much overhead in all the emulation that needs to be
done.
-One of the reasons people write C extensions is for speed. Often, with PyPy
-you can
-just forget about C, write everything in pure python and let the JIT to do its
-magic.
+One of the reasons people write C extensions is for speed. Often, with PyPy
+you can just forget about C, write everything in pure python and let the JIT to
+do its magic.
In case the PyPy JIT alone isn't fast enough, or you just want to
use existing C code then it might make sense to split
@@ -59,7 +58,6 @@
thus can be loaded with ``ctypes`` and called from PyPy, and another which does
the interfacing with Python for CPython (where it will be faster).
-XXX I find this pararagraph unclear.
There are also libraries written in C to interface with existing C codebases,
but for whom performance is not the largest goal, for these the right solution
is to try using CPyExt, and if it works that's great, but if it fails the
@@ -70,16 +68,17 @@
And finally there are rare cases where rewriting in RPython makes more sense,
NumPy is one of the few examples of these because we need to be able to give
the JIT hints on how to appropriately vectorize all of the operations on an
-array. XXX Why? How can you recognize a library that should be rewritten
-in RPython compared to one that shouldn't? Should this be done for all
-speed critical libraries, or just certain ones, and if the latter, which?
+array. In general writing in RPython is not necessary for almost any
+libraries, NumPy is something of a special case because it is so ubiquitous
+that every ounce of speed is valuable, and makes the way people use it leads to
+code structure where the JIT benefits enormously from extra hints.
Progress
--------
On a more positive note, after we published the `last post`_, several new people
-came and contributed improvements to the numpy-exp branch.
-We would like to thank all of them:
+came and contributed improvements to the ``numpy-exp`` branch. We would like to
+thank all of them:
* nightless_night contributed: An implementation of ``__len__``, fixed bounds
checks on ``__getitem__`` and ``__setitem__``.
From commits-noreply at bitbucket.org Thu May 5 22:45:36 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 22:45:36 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: More details.
Message-ID: <20110505204536.AE496282B58@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3572:c6caf915799f
Date: 2011-05-05 16:45 -0400
http://bitbucket.org/pypy/extradoc/changeset/c6caf915799f/
Log: More details.
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -30,6 +30,10 @@
a much faster NumPy, in a way that's more fun, and given that the people
working on this are volunteers, it's important to keep us motivated.
+Finally, we are **not** proposing to rewrite the entirety of NumPy or, god
+forbid, BLAST, or any of the low level stuff that operates on C-level arrays,
+only the parts that interface with Python code directly.
+
C bindings vs. CPython C-API
----------------------------
@@ -64,14 +68,14 @@
solution will be to rewrite using `ctypes`, where it will work on all Python
VMs, not just CPython.
-
And finally there are rare cases where rewriting in RPython makes more sense,
NumPy is one of the few examples of these because we need to be able to give
the JIT hints on how to appropriately vectorize all of the operations on an
array. In general writing in RPython is not necessary for almost any
libraries, NumPy is something of a special case because it is so ubiquitous
that every ounce of speed is valuable, and makes the way people use it leads to
-code structure where the JIT benefits enormously from extra hints.
+code structure where the JIT benefits enormously from extra hints and the
+ability to manipulate memory directly.
Progress
--------
From commits-noreply at bitbucket.org Thu May 5 22:49:00 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 22:49:00 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: (fijal) note
Message-ID: <20110505204900.F3DBB282B58@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3573:e9bff972d057
Date: 2011-05-05 16:48 -0400
http://bitbucket.org/pypy/extradoc/changeset/e9bff972d057/
Log: (fijal) note
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -75,7 +75,7 @@
libraries, NumPy is something of a special case because it is so ubiquitous
that every ounce of speed is valuable, and makes the way people use it leads to
code structure where the JIT benefits enormously from extra hints and the
-ability to manipulate memory directly.
+ability to manipulate memory directly, which is not possible from Python.
Progress
--------
From commits-noreply at bitbucket.org Thu May 5 23:18:56 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Thu, 5 May 2011 23:18:56 +0200 (CEST)
Subject: [pypy-svn] extradoc extradoc: fix links.
Message-ID: <20110505211856.BCE19282B8E@codespeak.net>
Author: Alex Gaynor
Branch: extradoc
Changeset: r3574:6f4721028c37
Date: 2011-05-05 17:18 -0400
http://bitbucket.org/pypy/extradoc/changeset/6f4721028c37/
Log: fix links.
diff --git a/blog/draft/numpy_followup.rst b/blog/draft/numpy_followup.rst
--- a/blog/draft/numpy_followup.rst
+++ b/blog/draft/numpy_followup.rst
@@ -94,8 +94,12 @@
hopefully you get the picture. In addition there was some exciting work done by
regular PyPy contributors. I hope it's clear that there's a place to jump in
for people with any level of PyPy familiarity. If you're interested in
-contributing please stop by #pypy on irc.freenode.net, the
-`pypy-dev `_ mailing list, or
-send us pull requests on `bitbucket `_.
+contributing please stop by #pypy on irc.freenode.net, the `pypy-dev`_ mailing
+list, or send us pull requests on `bitbucket`_.
Alex
+
+
+.. _`last post`: http://morepypy.blogspot.com/2011/05/numpy-in-pypy-status-and-roadmap.html
+.. _`pypy-dev`: http://codespeak.net/mailman/listinfo/pypy-dev
+.. _`bitbucket`: https://bitbucket.org/pypy/pypy
\ No newline at end of file
From commits-noreply at bitbucket.org Fri May 6 00:30:35 2011
From: commits-noreply at bitbucket.org (alex_gaynor)
Date: Fri, 6 May 2011 00:30:35 +0200 (CEST)
Subject: [pypy-svn] pypy numpy-exp: A little reorganization,
now that we have Code objects make things methods.
Message-ID: <20110505223035.8E511282B58@codespeak.net>
Author: Alex Gaynor
Branch: numpy-exp
Changeset: r43917:be6e80600ff9
Date: 2011-05-05 18:30 -0400
http://bitbucket.org/pypy/pypy/changeset/be6e80600ff9/
Log: A little reorganization, now that we have Code objects make things
methods.
diff --git a/pypy/module/micronumpy/numarray.py b/pypy/module/micronumpy/numarray.py
--- a/pypy/module/micronumpy/numarray.py
+++ b/pypy/module/micronumpy/numarray.py
@@ -82,65 +82,74 @@
self.arrays + other.arrays,
self.floats + other.floats)
-def compute(code):
- """
- Crunch a ``Code`` full of bytecode.
- """
+ def intern(self):
+ # the point of these hacks is to intern the bytecode string otherwise
+ # we have to compile new assembler each time, which sucks (we still
+ # have to compile new bytecode, but too bad)
+ try:
+ self.bytecode = JITCODES[self.bytecode]
+ except KeyError:
+ JITCODES[self.bytecode] = self.bytecode
- bytecode = code.bytecode
- result_size = code.arrays[0].size
- result = SingleDimArray(result_size)
- bytecode_pos = len(bytecode) - 1
- i = 0
- frame = ComputationFrame(code.arrays, code.floats)
- while i < result_size:
- numpy_driver.jit_merge_point(bytecode=bytecode, result=result,
- result_size=result_size,
- i=i, frame=frame,
- bytecode_pos=bytecode_pos)
- if bytecode_pos == -1:
- bytecode_pos = len(bytecode) - 1
- frame.reset()
- result.storage[i] = frame.valuestack[0]
- i += 1
- numpy_driver.can_enter_jit(bytecode=bytecode, result=result,
- result_size=result_size,
- i=i, frame=frame,
- bytecode_pos=bytecode_pos)
- else:
- opcode = bytecode[bytecode_pos]
- if opcode == 'l':
- # Load array.
- val = frame.getarray().storage[i]
- frame.pushvalue(val)
- elif opcode == 'f':
- # Load float.
- val = frame.getfloat()
- frame.pushvalue(val)
- elif opcode == 'a':
- # Add.
- a = frame.popvalue()
- b = frame.popvalue()
- frame.pushvalue(a + b)
- elif opcode == 's':
- # Subtract
- a = frame.popvalue()
- b = frame.popvalue()
- frame.pushvalue(a - b)
- elif opcode == 'm':
- # Multiply.
- a = frame.popvalue()
- b = frame.popvalue()
- frame.pushvalue(a * b)
- elif opcode == 'd':
- a = frame.popvalue()
- b = frame.popvalue()
- frame.pushvalue(a / b)
+ def compute(self):
+ """
+ Crunch a ``Code`` full of bytecode.
+ """
+
+ bytecode = self.bytecode
+ result_size = self.arrays[0].size
+ result = SingleDimArray(result_size)
+ bytecode_pos = len(bytecode) - 1
+ i = 0
+ frame = ComputationFrame(self.arrays, self.floats)
+ while i < result_size:
+ numpy_driver.jit_merge_point(bytecode=bytecode, result=result,
+ result_size=result_size,
+ i=i, frame=frame,
+ bytecode_pos=bytecode_pos)
+ if bytecode_pos == -1:
+ bytecode_pos = len(bytecode) - 1
+ frame.reset()
+ result.storage[i] = frame.valuestack[0]
+ i += 1
+ numpy_driver.can_enter_jit(bytecode=bytecode, result=result,
+ result_size=result_size,
+ i=i, frame=frame,
+ bytecode_pos=bytecode_pos)
else:
- raise NotImplementedError(
- "Can't handle bytecode instruction %s" % opcode)
- bytecode_pos -= 1
- return result
+ opcode = bytecode[bytecode_pos]
+ if opcode == 'l':
+ # Load array.
+ val = frame.getarray().storage[i]
+ frame.pushvalue(val)
+ elif opcode == 'f':
+ # Load float.
+ val = frame.getfloat()
+ frame.pushvalue(val)
+ elif opcode == 'a':
+ # Add.
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a + b)
+ elif opcode == 's':
+ # Subtract
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a - b)
+ elif opcode == 'm':
+ # Multiply.
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a * b)
+ elif opcode == 'd':
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a / b)
+ else:
+ raise NotImplementedError(
+ "Can't handle bytecode instruction %s" % opcode)
+ bytecode_pos -= 1
+ return result
JITCODES = {}
@@ -150,14 +159,8 @@
def force(self):
code = self.compile()
- try:
- code.bytecode = JITCODES[code.bytecode]
- except KeyError:
- JITCODES[code.bytecode] = code.bytecode
- # the point of above hacks is to intern the bytecode string
- # otherwise we have to compile new assembler each time, which sucks
- # (we still have to compile new bytecode, but too bad)
- return compute(code)
+ code.intern()
+ return code.compute()
def invalidated(self):
for arr in self.invalidates:
From commits-noreply at bitbucket.org Fri May 6 08:40:23 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Fri, 6 May 2011 08:40:23 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: tests
Message-ID: <20110506064023.40E7C282B58@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43918:830a12ab64d8
Date: 2011-05-06 08:39 +0200
http://bitbucket.org/pypy/pypy/changeset/830a12ab64d8/
Log: tests
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -2911,6 +2911,54 @@
"""
self.optimize_loop(ops, expected, preamble)
+ def test_ovf_guard_in_short_preamble1(self):
+ ops = """
+ [p8, p11, i24]
+ p26 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p26, i24, descr=adescr)
+ i34 = getfield_gc_pure(p11, descr=valuedescr)
+ i35 = getfield_gc_pure(p26, descr=adescr)
+ i36 = int_add_ovf(i34, i35)
+ guard_no_overflow() []
+ jump(p8, p11, i35)
+ """
+ expected = """
+ [p8, p11, i26]
+ jump(p8, p11, i26)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_ovf_guard_in_short_preamble2(self):
+ ops = """
+ [p8, p11, p12]
+ p16 = getfield_gc(p8, descr=valuedescr)
+ i17 = getfield_gc(p8, descr=nextdescr)
+ i19 = getfield_gc(p16, descr=valuedescr)
+ i20 = int_ge(i17, i19)
+ guard_false(i20) []
+ i21 = getfield_gc(p16, descr=otherdescr)
+ i22 = getfield_gc(p16, descr=nextdescr)
+ i23 = int_mul(i17, i22)
+ i24 = int_add(i21, i23)
+ p26 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p26, i24, descr=adescr)
+ i28 = int_add(i17, 1)
+ setfield_gc(p8, i28, descr=nextdescr)
+ i34 = getfield_gc_pure(p11, descr=valuedescr)
+ i35 = getfield_gc_pure(p26, descr=adescr)
+ i36 = int_add_ovf(i34, i35)
+ guard_no_overflow() []
+ p38 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p38, i36, descr=adescr)
+ jump(p8, p11, p26)
+ """
+ expected = """
+ [i34, i17, i22]
+ jump(i34, i17, i22)
+ """
+ self.optimize_loop(ops, expected)
+
+
def test_int_and_or_with_zero(self):
ops = """
[i0, i1]
From commits-noreply at bitbucket.org Fri May 6 09:09:28 2011
From: commits-noreply at bitbucket.org (fijal)
Date: Fri, 6 May 2011 09:09:28 +0200 (CEST)
Subject: [pypy-svn] pypy default: remove old obscure unused files
Message-ID: <20110506070928.95236282B58@codespeak.net>
Author: Maciej Fijalkowski
Branch:
Changeset: r43919:310d7cd53ad7
Date: 2011-05-06 09:09 +0200
http://bitbucket.org/pypy/pypy/changeset/310d7cd53ad7/
Log: remove old obscure unused files
diff --git a/pypy/tool/algo/test/test_unionref.py b/pypy/tool/algo/test/test_unionref.py
deleted file mode 100644
--- a/pypy/tool/algo/test/test_unionref.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from pypy.tool.algo.unionref import UnionRef, UnionDict
-
-def test_ref():
- x = object()
- ref = UnionRef(x)
- assert ref() is x
- assert ref == ref
- assert ref != UnionRef(x)
-
-def test_merge():
- d1 = {1: '1'}
- d2 = {2: '2'}
- d3 = {3: '3'}
- d4 = {4: '4'}
- r1 = UnionRef(d1)
- r2 = UnionRef(d2)
- r3 = UnionRef(d3)
- r4 = UnionRef(d4)
- r1.merge(r1)
- assert r1 != r2 != r3 != r4
- r1.merge(r2)
- assert r1() is r2() == {1: '1', 2: '2'}
- assert r1 == r2
- r3.merge(r4)
- assert r3() is r4() == {3: '3', 4: '4'}
- assert r1 != r3
- assert r2 != r3
- assert r1 != r4
- assert r2 != r4
- r1.merge(r4)
- assert r1() is r2() is r3() is r4() == {1: '1', 2: '2', 3: '3', 4: '4'}
- assert r1 == r2 == r3 == r4
-
-def test_uniondict():
- k1 = object()
- k2 = object()
- k3 = object()
- k4 = object()
- d = UnionDict()
- d[k1] = {1: '1'}
- d[k2] = {2: '2'}
- d[k3] = {3: '3'}
- d[k4] = {4: '4'}
- assert d[k1] == {1: '1'}
- assert d[k2] == {2: '2'}
- assert d[k3] == {3: '3'}
- assert d[k4] == {4: '4'}
- assert len(d) == 4
- d.merge(k1, k2)
- d.merge(k3, k4)
- assert d[k1] is d[k2] == {1: '1', 2: '2'}
- assert d[k3] is d[k4] == {3: '3', 4: '4'}
- d.merge(k1, k4)
- assert d[k1] is d[k2] is d[k3] is d[k4] == {1: '1', 2: '2', 3: '3', 4: '4'}
- assert len(d) == 4
diff --git a/pypy/tool/algo/unionref.py b/pypy/tool/algo/unionref.py
deleted file mode 100644
--- a/pypy/tool/algo/unionref.py
+++ /dev/null
@@ -1,151 +0,0 @@
-"""
-ref = UnionRef(x) -> creates a reference to x, such that ref() is x.
-
-Two references can be merged: ref.merge(ref2) make ref and ref2 interchangeable.
-After a merge, ref() is ref2(). This is done by asking the two older objects
-that ref and ref2 pointed to how they should be merged. The point is that
-large equivalence relations can be built this way:
-
- >>> ref1.merge(ref2)
- >>> ref3.merge(ref4)
- >>> ref1() is ref4()
- False
- >>> ref2.merge(ref3)
- >>> ref1() is ref4()
- True
-
-By default, two objects x and y are merged by calling x.update(y).
-"""
-
-import UserDict
-from pypy.tool.uid import uid
-
-
-class UnionRef(object):
- __slots__ = ('_obj', '_parent', '_weight')
-
- def __init__(self, obj):
- "Build a new reference to 'obj'."
- self._obj = obj
- self._parent = None
- self._weight = 1
-
- def __call__(self):
- "Return the 'obj' that self currently references."
- return self._findrep()._obj
-
- def _findrep(self):
- p = self._parent
- if p:
- if p._parent:
- # this linked list is unnecessarily long, shorten it
- path = [self]
- while p._parent:
- path.append(p)
- p = p._parent
- for q in path:
- q._parent = p
- return p
- return self
-
- def merge(self, other, union=None):
- "Merge two references. After a.merge(b), a() and b() are identical."
- self = self ._findrep()
- other = other._findrep()
- if self is not other:
- w1 = self ._weight
- w2 = other._weight
- if w1 < w2:
- self, other = other, self
- self._weight = w1 + w2
- other._parent = self
- o = other._obj
- del other._obj
- if union is not None:
- self._obj = union(self._obj, o)
- else:
- self.update(o)
- return self
-
- def update(self, obj):
- "Merge 'obj' in self. Default implementation, can be overridden."
- self._obj.update(obj)
-
- def __hash__(self):
- raise TypeError("UnionRef objects are unhashable")
-
- def __eq__(self, other):
- return (isinstance(other, UnionRef) and
- self._findrep() is other._findrep())
-
- def __ne__(self, other):
- return not (self == other)
-
-
-class UnionDict(object, UserDict.DictMixin):
- """Mapping class whose items can be unified. Conceptually, instead of
- a set of (key, value) pairs, this is a set of ({keys}, value) pairs.
- The method merge(key1, key2) merges the two pairs containing, respectively,
- key1 and key2.
- """
- _slots = ('_data',)
-
- def __init__(self, dict=None, **kwargs):
- self._data = {}
- if dict is not None:
- self.update(dict)
- if len(kwargs):
- self.update(kwargs)
-
- def merge(self, key1, key2, union=None):
- self._data[key1] = self._data[key1].merge(self._data[key2], union)
-
- def copy(self):
- result = UnionDict()
- newrefs = {}
- for key, valueref in self._data.iteritems():
- valueref = valueref._findrep()
- try:
- newref = newrefs[valueref]
- except KeyError:
- newref = newrefs[valueref] = UnionRef(valueref())
- result._data[key] = newref
- return result
-
- def __repr__(self):
- return "" % uid(self)
-
- def __getitem__(self, key):
- return self._data[key]()
-
- def __setitem__(self, key, value):
- self._data[key] = UnionRef(value)
-
- def __delitem__(self, key):
- del self._data[key]
-
- def keys(self):
- return self._data.keys()
-
- def has_key(self, key):
- return key in self._data
-
- def __contains__(self, key):
- return key in self._data
-
- def __iter__(self):
- return iter(self._data)
-
- def iteritems(self):
- for key, valueref in self._data.iteritems():
- yield (key, valueref())
-
- def clear(self):
- self._data.clear()
-
- def popitem(self):
- key, valueref = self._data.popitem()
- return key, valueref()
-
- def __len__(self):
- return len(self._data)
From commits-noreply at bitbucket.org Fri May 6 09:49:41 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Fri, 6 May 2011 09:49:41 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: Removing duplicated ovf ops
does not work if there are lazy setfields. They will be
inserted between int_add_ovf and guard_no_overflow prevent
the optimization. Later on operations are swapped in
newoperations to place int_add_ovf and guard_no_overflow next
to eachother in the final optimized trace.
Message-ID: <20110506074941.DBF46282B58@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43920:15e6730794b8
Date: 2011-05-06 09:48 +0200
http://bitbucket.org/pypy/pypy/changeset/15e6730794b8/
Log: Removing duplicated ovf ops does not work if there are lazy
setfields. They will be inserted between int_add_ovf and
guard_no_overflow prevent the optimization. Later on operations are
swapped in newoperations to place int_add_ovf and guard_no_overflow
next to eachother in the final optimized trace.
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -2911,6 +2911,42 @@
"""
self.optimize_loop(ops, expected, preamble)
+ def test_remove_duplicate_pure_op_ovf_with_lazy_setfield(self):
+ ops = """
+ [i1, p1]
+ i3 = int_add_ovf(i1, 1)
+ guard_no_overflow() []
+ i3b = int_is_true(i3)
+ guard_true(i3b) []
+ setfield_gc(p1, i1, descr=valuedescr)
+ i4 = int_add_ovf(i1, 1)
+ guard_no_overflow() []
+ i4b = int_is_true(i4)
+ guard_true(i4b) []
+ escape(i3)
+ escape(i4)
+ jump(i1, p1)
+ """
+ preamble = """
+ [i1, p1]
+ i3 = int_add_ovf(i1, 1)
+ guard_no_overflow() []
+ i3b = int_is_true(i3)
+ guard_true(i3b) []
+ setfield_gc(p1, i1, descr=valuedescr)
+ escape(i3)
+ escape(i3)
+ jump(i1, p1, i3)
+ """
+ expected = """
+ [i1, p1, i3]
+ setfield_gc(p1, i1, descr=valuedescr)
+ escape(i3)
+ escape(i3)
+ jump(i1, p1, i3)
+ """
+ self.optimize_loop(ops, expected, preamble)
+
def test_ovf_guard_in_short_preamble1(self):
ops = """
[p8, p11, i24]
@@ -2946,6 +2982,7 @@
setfield_gc(p8, i28, descr=nextdescr)
i34 = getfield_gc_pure(p11, descr=valuedescr)
i35 = getfield_gc_pure(p26, descr=adescr)
+ guard_nonnull(p12) []
i36 = int_add_ovf(i34, i35)
guard_no_overflow() []
p38 = new_with_vtable(ConstClass(node_vtable))
From commits-noreply at bitbucket.org Fri May 6 12:00:43 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Fri, 6 May 2011 12:00:43 +0200 (CEST)
Subject: [pypy-svn] pypy default: issue712 resolved
Message-ID: <20110506100043.E06BE282B58@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43925:68e9165bb142
Date: 2011-05-06 11:49 +0200
http://bitbucket.org/pypy/pypy/changeset/68e9165bb142/
Log: issue712 resolved
Fix the test to conform to CPython's behavior (as tested with -A).
Fix the code accordingly.
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1417,13 +1417,16 @@
def print_item_to(x, stream):
if file_softspace(stream, False):
stream.write(" ")
- if isinstance(x, unicode) and getattr(stream, "encoding", None) is not None:
- x = x.encode(stream.encoding, getattr(stream, "errors", None) or "strict")
- stream.write(str(x))
+
+ # give to write() an argument which is either a string or a unicode
+ # (and let it deals itself with unicode handling)
+ if not isinstance(x, unicode):
+ x = str(x)
+ stream.write(x)
# add a softspace unless we just printed a string which ends in a '\t'
# or '\n' -- or more generally any whitespace character but ' '
- if isinstance(x, (str, unicode)) and x:
+ if x:
lastchar = x[-1]
if lastchar.isspace() and lastchar != ' ':
return
diff --git a/pypy/interpreter/test/test_interpreter.py b/pypy/interpreter/test/test_interpreter.py
--- a/pypy/interpreter/test/test_interpreter.py
+++ b/pypy/interpreter/test/test_interpreter.py
@@ -277,20 +277,25 @@
class Out(object):
def __init__(self):
self.data = []
-
def write(self, x):
- self.data.append(x)
+ self.data.append((type(x), x))
sys.stdout = out = Out()
try:
- raises(UnicodeError, "print unichr(0xa2)")
- assert out.data == []
- out.encoding = "cp424"
print unichr(0xa2)
- assert out.data == [unichr(0xa2).encode("cp424"), "\n"]
+ assert out.data == [(unicode, unichr(0xa2)), (str, "\n")]
+ out.data = []
+ out.encoding = "cp424" # ignored!
+ print unichr(0xa2)
+ assert out.data == [(unicode, unichr(0xa2)), (str, "\n")]
del out.data[:]
del out.encoding
print u"foo\t", u"bar\n", u"trick", u"baz\n" # softspace handling
- assert out.data == ["foo\t", "bar\n", "trick", " ", "baz\n", "\n"]
+ assert out.data == [(unicode, "foo\t"),
+ (unicode, "bar\n"),
+ (unicode, "trick"),
+ (str, " "),
+ (unicode, "baz\n"),
+ (str, "\n")]
finally:
sys.stdout = save
From commits-noreply at bitbucket.org Fri May 6 12:50:17 2011
From: commits-noreply at bitbucket.org (hakanardo)
Date: Fri, 6 May 2011 12:50:17 +0200 (CEST)
Subject: [pypy-svn] pypy jit-short_from_state: emit guards from
short_preamble with proper desc at end of loop in case the
optimizer is not able to remove them
Message-ID: <20110506105017.E9AF8282B58@codespeak.net>
Author: Hakan Ardo
Branch: jit-short_from_state
Changeset: r43926:6db30e2775cc
Date: 2011-05-06 12:37 +0200
http://bitbucket.org/pypy/pypy/changeset/6db30e2775cc/
Log: emit guards from short_preamble with proper desc at end of loop in
case the optimizer is not able to remove them
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -175,6 +175,23 @@
self.constant_inputargs[box] = const
initial_inputargs_len = len(inputargs)
+ self.inliner = Inliner(loop.inputargs, jump_args)
+
+ start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
+ self.start_resumedescr = start_resumedescr
+ assert isinstance(start_resumedescr, ResumeGuardDescr)
+ snapshot = start_resumedescr.rd_snapshot
+ while snapshot is not None:
+ snapshot_args = snapshot.boxes
+ new_snapshot_args = []
+ for a in snapshot_args:
+ if not isinstance(a, Const):
+ a = loop.preamble.inputargs[jump_args.index(a)]
+ a = self.inliner.inline_arg(a)
+ a = self.getvalue(a).get_key_box()
+ new_snapshot_args.append(a)
+ snapshot.boxes = new_snapshot_args
+ snapshot = snapshot.prev
inputargs, short_inputargs, short = self.inline(self.cloned_operations,
loop.inputargs, jump_args,
@@ -192,21 +209,6 @@
loop.operations = self.optimizer.newoperations
- start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
- assert isinstance(start_resumedescr, ResumeGuardDescr)
- snapshot = start_resumedescr.rd_snapshot
- while snapshot is not None:
- snapshot_args = snapshot.boxes
- new_snapshot_args = []
- for a in snapshot_args:
- if not isinstance(a, Const):
- a = loop.preamble.inputargs[jump_args.index(a)]
- a = self.inliner.inline_arg(a)
- a = self.getvalue(a).get_key_box()
- new_snapshot_args.append(a)
- snapshot.boxes = new_snapshot_args
- snapshot = snapshot.prev
-
#short = self.create_short_preamble(loop.preamble, loop)
if short:
assert short[-1].getopnum() == rop.JUMP
@@ -218,7 +220,7 @@
if op.is_guard():
op = op.clone()
op.setfailargs(None)
- descr = start_resumedescr.clone_if_mutable()
+ descr = self.start_resumedescr.clone_if_mutable()
op.setdescr(descr)
short[i] = op
@@ -234,7 +236,7 @@
short_loop.inputargs = newargs
ops = [inliner.inline_op(op) for op in short_loop.operations]
short_loop.operations = ops
- descr = start_resumedescr.clone_if_mutable()
+ descr = self.start_resumedescr.clone_if_mutable()
inliner.inline_descr_inplace(descr)
short_loop.start_resumedescr = descr
@@ -253,7 +255,7 @@
op.result.forget_value()
def inline(self, loop_operations, loop_args, jump_args, virtual_state):
- self.inliner = inliner = Inliner(loop_args, jump_args)
+ inliner = self.inliner
values = [self.getvalue(arg) for arg in jump_args]
inputargs = virtual_state.make_inputargs(values)
@@ -320,29 +322,26 @@
def add_op_to_short(self, op, short, short_seen):
if op is None:
- return
+ return
if op.result is not None and op.result in short_seen:
return self.short_inliner.inline_arg(op.result)
for a in op.getarglist():
if not isinstance(a, Const) and a not in short_seen:
self.add_op_to_short(self.short_boxes[a], short, short_seen)
+ if op.is_guard():
+ descr = self.start_resumedescr.clone_if_mutable()
+ op.setdescr(descr)
+
short.append(op)
short_seen[op.result] = True
newop = self.short_inliner.inline_op(op)
- newoplen = len(self.optimizer.newoperations)
self.optimizer.send_extra_operation(newop)
- assert len(self.optimizer.newoperations) == newoplen
if op.is_ovf():
# FIXME: ensure that GUARD_OVERFLOW:ed ops not end up here
guard = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
- short.append(guard)
- newoplen = len(self.optimizer.newoperations)
- self.optimizer.send_extra_operation(guard)
- assert len(self.optimizer.newoperations) == newoplen
+ self.add_op_to_short(guard, short, short_seen)
- # FIXME: Emit a proper guards here in case it is not
- # removed by the optimizer. Can that happen?
return newop.result
def import_box(self, box, inputargs, short, short_jumpargs,
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2355,6 +2355,25 @@
return f(n, A(5), A(10))
assert self.meta_interp(g, [20]) == g(20)
+ def test_ovf_guard_in_short_preamble2(self):
+ class A(object):
+ def __init__(self, val):
+ self.val = val
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a', 'node1', 'node2'])
+ def f(n, a):
+ node1 = node2 = A(0)
+ sa = i = 0
+ while i < n:
+ myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a, node1=node1, node2=node2)
+ node2.val = 7
+ if a >= 100:
+ sa += 1
+ sa += ovfcheck(i + i)
+ node1 = A(i)
+ i += 1
+ assert self.meta_interp(f, [20, 7]) == f(20, 7)
+
+
class TestOOtype(BasicTests, OOJitMixin):
def test_oohash(self):
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -193,6 +193,8 @@
boxes = []
def clone_if_mutable(self):
return self
+ def __eq__(self, other):
+ return isinstance(other, Storage) or isinstance(other, FakeDescr)
loop.preamble.start_resumedescr = FakeDescr()
optimize_loop_1(metainterp_sd, loop, ALL_OPTS_DICT)
#
@@ -2990,8 +2992,20 @@
jump(p8, p11, p26)
"""
expected = """
- [i34, i17, i22]
- jump(i34, i17, i22)
+ [p8, p11, i24, i19, p16, i21, i34]
+ i39 = getfield_gc(p8, descr=nextdescr)
+ i40 = int_ge(i39, i19)
+ guard_false(i40) []
+ i41 = getfield_gc(p16, descr=nextdescr)
+ i42 = int_mul(i39, i41)
+ i43 = int_add(i21, i42)
+ i44 = int_add(i39, 1)
+ setfield_gc(p8, i44, descr=nextdescr)
+ i45 = int_add_ovf(i34, i43)
+ guard_no_overflow() []
+ i46 = int_add_ovf(i34, i43)
+ guard_no_overflow() []
+ jump(p8, p11, i43, i19, p16, i21, i34)
"""
self.optimize_loop(ops, expected)
From commits-noreply at bitbucket.org Fri May 6 15:24:29 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Fri, 6 May 2011 15:24:29 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Add a marker '<====' on the
first line containing the difference.
Message-ID: <20110506132429.3EA4F282B90@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43927:042564868388
Date: 2011-05-06 13:22 +0000
http://bitbucket.org/pypy/pypy/changeset/042564868388/
Log: Add a marker '<====' on the first line containing the difference.
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -173,6 +173,7 @@
return matcher.match(expected_src)
class InvalidMatch(Exception):
+ opindex = None
def __init__(self, message, frame):
Exception.__init__(self, message)
@@ -332,31 +333,39 @@
"""
iter_exp_ops = iter(expected_ops)
iter_ops = iter(self.ops)
- for exp_op in iter_exp_ops:
- if exp_op == '...':
- # loop until we find an operation which matches
- try:
- exp_op = iter_exp_ops.next()
- except StopIteration:
- # the ... is the last line in the expected_ops, so we just
- # return because it matches everything until the end
- return
- op = self.match_until(exp_op, iter_ops)
- else:
- while True:
- op = self._next_op(iter_ops)
- if op.name not in ignore_ops:
- break
- self.match_op(op, exp_op)
+ for opindex, exp_op in enumerate(iter_exp_ops):
+ try:
+ if exp_op == '...':
+ # loop until we find an operation which matches
+ try:
+ exp_op = iter_exp_ops.next()
+ except StopIteration:
+ # the ... is the last line in the expected_ops, so we just
+ # return because it matches everything until the end
+ return
+ op = self.match_until(exp_op, iter_ops)
+ else:
+ while True:
+ op = self._next_op(iter_ops)
+ if op.name not in ignore_ops:
+ break
+ self.match_op(op, exp_op)
+ except InvalidMatch, e:
+ e.opindex = opindex
+ raise
#
# make sure we exhausted iter_ops
self._next_op(iter_ops, assert_raises=True)
def match(self, expected_src, ignore_ops=[]):
- def format(src):
+ def format(src, opindex=None):
if src is None:
return ''
- return py.code.Source(src).deindent().indent()
+ text = str(py.code.Source(src).deindent().indent())
+ lines = text.splitlines(True)
+ if opindex is not None and 0 <= opindex < len(lines):
+ lines[opindex] = lines[opindex].rstrip() + '\t<=====\n'
+ return ''.join(lines)
#
expected_src = self.preprocess_expected_src(expected_src)
expected_ops = self.parse_ops(expected_src)
@@ -372,7 +381,7 @@
print
print "Ignore ops:", ignore_ops
print "Got:"
- print format(self.src)
+ print format(self.src, e.opindex)
print
print "Expected:"
print format(expected_src)
From commits-noreply at bitbucket.org Fri May 6 15:24:30 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Fri, 6 May 2011 15:24:30 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Finish adapting to
out-of-line-guards-2.
Message-ID: <20110506132430.6972C282B90@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43928:6ab51a504cbb
Date: 2011-05-06 13:22 +0000
http://bitbucket.org/pypy/pypy/changeset/6ab51a504cbb/
Log: Finish adapting to out-of-line-guards-2.
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -509,15 +509,15 @@
i20 = int_add(i11, 1)
i21 = force_token()
setfield_gc(p4, i20, descr=<.* .*W_AbstractSeqIterObject.inst_index .*>)
+ guard_not_invalidated(descr=)
i23 = int_lt(i18, 0)
- guard_false(i23, descr=)
+ guard_false(i23, descr=)
i25 = int_ge(i18, i9)
- guard_false(i25, descr=)
- i26 = int_mul(i18, i10)
- i27 = int_add_ovf(i7, i26)
- guard_no_overflow(descr=)
+ guard_false(i25, descr=)
+ i27 = int_add_ovf(i7, i18)
+ guard_no_overflow(descr=)
--TICK--
- jump(p0, p1, p2, p3, p4, p5, p6, i27, i18, i9, i10, i20, i12, p13, i14, i15, descr=)
+ jump(..., descr=)
""")
def test_exception_inside_loop_1(self):
@@ -536,11 +536,12 @@
assert loop.match("""
i5 = int_is_true(i3)
guard_true(i5, descr=)
+ guard_not_invalidated(descr=)
--EXC-TICK--
i12 = int_sub_ovf(i3, 1)
- guard_no_overflow(descr=)
+ guard_no_overflow(descr=)
--TICK--
- jump(p0, p1, p2, i12, descr=)
+ jump(..., descr=)
""")
def test_exception_inside_loop_2(self):
@@ -583,10 +584,11 @@
assert loop.match("""
i7 = int_lt(i4, i5)
guard_true(i7, descr=)
+ guard_not_invalidated(descr=)
--EXC-TICK--
i14 = int_add(i4, 1)
--TICK--
- jump(p0, p1, p2, p3, i14, i5, descr=)
+ jump(..., descr=)
""")
def test_chain_of_guards(self):
@@ -688,10 +690,11 @@
assert loop.match_by_id('import', """
p11 = getfield_gc(ConstPtr(ptr10), descr=)
guard_value(p11, ConstPtr(ptr12), descr=)
+ guard_not_invalidated(descr=)
p14 = getfield_gc(ConstPtr(ptr13), descr=)
p16 = getfield_gc(ConstPtr(ptr15), descr=)
- guard_value(p14, ConstPtr(ptr17), descr=)
- guard_isnull(p16, descr=)
+ guard_value(p14, ConstPtr(ptr17), descr=)
+ guard_isnull(p16, descr=)
""")
def test_import_fast_path(self, tmpdir):
@@ -1112,7 +1115,7 @@
# -------------------------------
entry_bridge, = log.loops_by_filename(self.filepath, is_entry_bridge=True)
ops = entry_bridge.ops_by_id('mutate', opcode='LOAD_ATTR')
- assert log.opnames(ops) == ['guard_value', 'getfield_gc', 'guard_value',
+ assert log.opnames(ops) == ['guard_value', 'guard_not_invalidated',
'getfield_gc', 'guard_nonnull_class']
# the STORE_ATTR is folded away
assert list(entry_bridge.ops_by_id('meth1', opcode='STORE_ATTR')) == []
@@ -1124,6 +1127,7 @@
i8 = getfield_gc_pure(p5, descr=)
i9 = int_lt(i8, i7)
guard_true(i9, descr=.*)
+ guard_not_invalidated(descr=.*)
i11 = int_add(i8, 1)
i12 = force_token()
--TICK--
From commits-noreply at bitbucket.org Fri May 6 15:24:32 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Fri, 6 May 2011 15:24:32 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: merge heads
Message-ID: <20110506132432.4712D2A2036@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43929:326cd5661f11
Date: 2011-05-06 13:24 +0000
http://bitbucket.org/pypy/pypy/changeset/326cd5661f11/
Log: merge heads
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -8,11 +8,11 @@
from pypy.jit.metainterp import pyjitpl, history
from pypy.jit.metainterp.warmstate import set_future_value
from pypy.jit.codewriter.policy import JitPolicy
-from pypy.jit.codewriter import longlong
+from pypy.jit.codewriter import codewriter, longlong
def _get_jitcodes(testself, CPUClass, func, values, type_system,
supports_longlong=False, **kwds):
- from pypy.jit.codewriter import support, codewriter
+ from pypy.jit.codewriter import support
class FakeJitCell:
__compiled_merge_points = []
@@ -49,6 +49,7 @@
stats = history.Stats()
cpu = CPUClass(rtyper, stats, None, False)
cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
+ cw.debug = True
testself.cw = cw
policy = JitPolicy()
policy.set_supports_longlong(supports_longlong)
@@ -171,7 +172,12 @@
kwds['type_system'] = self.type_system
if "backendopt" not in kwds:
kwds["backendopt"] = False
- return ll_meta_interp(*args, **kwds)
+ old = codewriter.CodeWriter.debug
+ try:
+ codewriter.CodeWriter.debug = True
+ return ll_meta_interp(*args, **kwds)
+ finally:
+ codewriter.CodeWriter.debug = old
def interp_operations(self, f, args, **kwds):
# get the JitCodes for the function f
diff --git a/pypy/jit/metainterp/test/test_jitprof.py b/pypy/jit/metainterp/test/test_jitprof.py
--- a/pypy/jit/metainterp/test/test_jitprof.py
+++ b/pypy/jit/metainterp/test/test_jitprof.py
@@ -65,7 +65,7 @@
]
assert profiler.events == expected
assert profiler.times == [3, 2, 1, 1]
- assert profiler.counters == [1, 2, 1, 1, 3, 3, 1, 13, 2, 0, 0, 0,
+ assert profiler.counters == [1, 2, 1, 1, 3, 3, 1, 13, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0]
def test_simple_loop_with_call(self):
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
@@ -389,12 +389,15 @@
assert isinstance(loop.quasi_immutable_deps.keys()[0], QuasiImmut)
def test_list_pass_around(self):
+ py.test.skip("think about a way to fix it")
myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
class Foo:
_immutable_fields_ = ['lst?[*]']
def __init__(self, lst):
self.lst = lst
def g(lst):
+ # here, 'lst' is statically annotated as a "modified" list,
+ # so the following doesn't generate a getarrayitem_gc_pure...
return lst[1]
def f(a, x):
lst1 = [0, 0]
From commits-noreply at bitbucket.org Fri May 6 15:58:36 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Fri, 6 May 2011 15:58:36 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Revert d5dd9462363a on
model.py. I'm unsure why, but it seems
Message-ID: <20110506135836.3AD68282B90@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43930:d83d8fdbe71a
Date: 2011-05-06 13:58 +0000
http://bitbucket.org/pypy/pypy/changeset/d83d8fdbe71a/
Log: Revert d5dd9462363a on model.py. I'm unsure why, but it seems that
all tests are happily working now...
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -250,7 +250,7 @@
# to repeat it every time
ticker_check = """
ticker0 = getfield_raw(ticker_address, descr=)
- ticker1 = int_sub(ticker0, _)
+ ticker1 = int_sub(ticker0, 1)
setfield_raw(ticker_address, ticker1, descr=)
ticker_cond0 = int_lt(ticker1, 0)
guard_false(ticker_cond0, descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1669,7 +1669,3 @@
assert log.result == 300
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id('shift', "") # optimized away
-
-
-def test_count():
- assert 0, "loops too long! revert d5dd9462363a on model.py"
From commits-noreply at bitbucket.org Fri May 6 16:27:19 2011
From: commits-noreply at bitbucket.org (bivab)
Date: Fri, 6 May 2011 16:27:19 +0200 (CEST)
Subject: [pypy-svn] pypy default: remove static keyword from
pypy_read_timestamp to match the definition in the header file
Message-ID: <20110506142719.689942A2033@codespeak.net>
Author: David Schneider
Branch:
Changeset: r43931:23bcf87e537e
Date: 2011-05-06 16:27 +0200
http://bitbucket.org/pypy/pypy/changeset/23bcf87e537e/
Log: remove static keyword from pypy_read_timestamp to match the
definition in the header file
diff --git a/pypy/translator/c/src/debug_print.c b/pypy/translator/c/src/debug_print.c
--- a/pypy/translator/c/src/debug_print.c
+++ b/pypy/translator/c/src/debug_print.c
@@ -74,7 +74,7 @@
#ifndef _WIN32
- static long long pypy_read_timestamp(void)
+ long long pypy_read_timestamp(void)
{
# ifdef CLOCK_THREAD_CPUTIME_ID
struct timespec tspec;
From commits-noreply at bitbucket.org Fri May 6 17:15:30 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Fri, 6 May 2011 17:15:30 +0200 (CEST)
Subject: [pypy-svn] pypy default: Write a more detailed __repr__ for
CallDescrs.
Message-ID: <20110506151530.C8F002A2033@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43932:a16fce4a93f5
Date: 2011-05-06 17:15 +0200
http://bitbucket.org/pypy/pypy/changeset/a16fce4a93f5/
Log: Write a more detailed __repr__ for CallDescrs.
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -261,6 +261,19 @@
self.arg_classes = arg_classes # string of "r" and "i" (ref/int)
self.extrainfo = extrainfo
+ def __repr__(self):
+ res = '%s(%s)' % (self.__class__.__name__, self.arg_classes)
+ oopspecindex = getattr(self.extrainfo, 'oopspecindex', 0)
+ if oopspecindex:
+ from pypy.jit.codewriter.effectinfo import EffectInfo
+ for key, value in EffectInfo.__dict__.items():
+ if key.startswith('OS_') and value == oopspecindex:
+ break
+ else:
+ key = 'oopspecindex=%r' % oopspecindex
+ res += ' ' + key
+ return '<%s>' % res
+
def get_extra_info(self):
return self.extrainfo
From commits-noreply at bitbucket.org Sat May 7 12:07:38 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sat, 7 May 2011 12:07:38 +0200 (CEST)
Subject: [pypy-svn] pypy default: Patch by qbproger: seems to be needed on
OpenSUSE for dlopen().
Message-ID: <20110507100738.E339E2A2035@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43933:33549b31a96d
Date: 2011-05-07 11:43 +0200
http://bitbucket.org/pypy/pypy/changeset/33549b31a96d/
Log: Patch by qbproger: seems to be needed on OpenSUSE for dlopen().
diff --git a/pypy/rpython/tool/rffi_platform.py b/pypy/rpython/tool/rffi_platform.py
--- a/pypy/rpython/tool/rffi_platform.py
+++ b/pypy/rpython/tool/rffi_platform.py
@@ -787,7 +787,7 @@
eci = ExternalCompilationInfo(
platform=platform,
includes=includes,
- libraries=['gc'],
+ libraries=['gc', 'dl'],
)
return configure_external_library(
'gc', eci,
From commits-noreply at bitbucket.org Sat May 7 12:07:40 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sat, 7 May 2011 12:07:40 +0200 (CEST)
Subject: [pypy-svn] pypy default: Enable supports_floats by default also
when running tests
Message-ID: <20110507100740.3D6562A2035@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43934:8a078727e654
Date: 2011-05-07 12:04 +0200
http://bitbucket.org/pypy/pypy/changeset/8a078727e654/
Log: Enable supports_floats by default also when running tests with
interp_operations(), not just meta_interp(). Caused some amount of
troubles to find out what was going on in the sqrtsd.patch.
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -51,6 +51,7 @@
cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
testself.cw = cw
policy = JitPolicy()
+ policy.set_supports_floats(True)
policy.set_supports_longlong(supports_longlong)
cw.find_all_graphs(policy)
#
From commits-noreply at bitbucket.org Sat May 7 12:07:42 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sat, 7 May 2011 12:07:42 +0200 (CEST)
Subject: [pypy-svn] pypy default: Patch by qbproger: write square roots with
the x86 SSE2
Message-ID: <20110507100742.A96AF2A2038@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43935:9439564ba9b3
Date: 2011-05-07 12:07 +0200
http://bitbucket.org/pypy/pypy/changeset/9439564ba9b3/
Log: Patch by qbproger: write square roots with the x86 SSE2 instruction
SQRTSD. Also cleans up a bit the error checking around math.sqrt().
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -832,6 +832,11 @@
effectinfo = op.getdescr().get_extra_info()
oopspecindex = effectinfo.oopspecindex
genop_llong_list[oopspecindex](self, op, arglocs, resloc)
+
+ def regalloc_perform_math(self, op, arglocs, resloc):
+ effectinfo = op.getdescr().get_extra_info()
+ oopspecindex = effectinfo.oopspecindex
+ genop_math_list[oopspecindex](self, op, arglocs, resloc)
def regalloc_perform_with_guard(self, op, guard_op, faillocs,
arglocs, resloc, current_depths):
@@ -1119,6 +1124,9 @@
genop_guard_float_eq = _cmpop_guard_float("E", "E", "NE","NE")
genop_guard_float_gt = _cmpop_guard_float("A", "B", "BE","AE")
genop_guard_float_ge = _cmpop_guard_float("AE","BE", "B", "A")
+
+ def genop_math_sqrt(self, op, arglocs, resloc):
+ self.mc.SQRTSD(arglocs[0], resloc)
def genop_guard_float_ne(self, op, guard_op, guard_token, arglocs, result_loc):
guard_opnum = guard_op.getopnum()
@@ -2158,6 +2166,7 @@
genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
genop_list = [Assembler386.not_implemented_op] * rop._LAST
genop_llong_list = {}
+genop_math_list = {}
genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST
for name, value in Assembler386.__dict__.iteritems():
@@ -2173,6 +2182,10 @@
opname = name[len('genop_llong_'):]
num = getattr(EffectInfo, 'OS_LLONG_' + opname.upper())
genop_llong_list[num] = value
+ elif name.startswith('genop_math_'):
+ opname = name[len('genop_math_'):]
+ num = getattr(EffectInfo, 'OS_MATH_' + opname.upper())
+ genop_math_list[num] = value
elif name.startswith('genop_'):
opname = name[len('genop_'):]
num = getattr(rop, opname.upper())
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -328,6 +328,11 @@
if not we_are_translated():
self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
self.assembler.regalloc_perform_llong(op, arglocs, result_loc)
+
+ def PerformMath(self, op, arglocs, result_loc):
+ if not we_are_translated():
+ self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
+ self.assembler.regalloc_perform_math(op, arglocs, result_loc)
def locs_for_fail(self, guard_op):
return [self.loc(v) for v in guard_op.getfailargs()]
@@ -661,15 +666,13 @@
consider_float_gt = _consider_float_cmp
consider_float_ge = _consider_float_cmp
- def consider_float_neg(self, op):
+ def _consider_float_unary_op(self, op):
loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(0))
self.Perform(op, [loc0], loc0)
self.xrm.possibly_free_var(op.getarg(0))
-
- def consider_float_abs(self, op):
- loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(0))
- self.Perform(op, [loc0], loc0)
- self.xrm.possibly_free_var(op.getarg(0))
+
+ consider_float_neg = _consider_float_unary_op
+ consider_float_abs = _consider_float_unary_op
def consider_cast_float_to_int(self, op):
loc0 = self.xrm.make_sure_var_in_reg(op.getarg(0))
@@ -755,6 +758,11 @@
loc1 = self.rm.make_sure_var_in_reg(op.getarg(1))
self.PerformLLong(op, [loc1], loc0)
self.rm.possibly_free_vars_for_op(op)
+
+ def _consider_math_sqrt(self, op):
+ loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(1))
+ self.PerformMath(op, [loc0], loc0)
+ self.xrm.possibly_free_var(op.getarg(1))
def _call(self, op, arglocs, force_store=[], guard_not_forced_op=None):
save_all_regs = guard_not_forced_op is not None
@@ -791,12 +799,12 @@
guard_not_forced_op=guard_not_forced_op)
def consider_call(self, op):
- if IS_X86_32:
- # support for some of the llong operations,
- # which only exist on x86-32
- effectinfo = op.getdescr().get_extra_info()
- if effectinfo is not None:
- oopspecindex = effectinfo.oopspecindex
+ effectinfo = op.getdescr().get_extra_info()
+ if effectinfo is not None:
+ oopspecindex = effectinfo.oopspecindex
+ if IS_X86_32:
+ # support for some of the llong operations,
+ # which only exist on x86-32
if oopspecindex in (EffectInfo.OS_LLONG_ADD,
EffectInfo.OS_LLONG_SUB,
EffectInfo.OS_LLONG_AND,
@@ -815,7 +823,8 @@
if oopspecindex == EffectInfo.OS_LLONG_LT:
if self._maybe_consider_llong_lt(op):
return
- #
+ if oopspecindex == EffectInfo.OS_MATH_SQRT:
+ return self._consider_math_sqrt(op)
self._consider_call(op)
def consider_call_may_force(self, op, guard_op):
diff --git a/pypy/jit/backend/x86/regloc.py b/pypy/jit/backend/x86/regloc.py
--- a/pypy/jit/backend/x86/regloc.py
+++ b/pypy/jit/backend/x86/regloc.py
@@ -515,6 +515,8 @@
UCOMISD = _binaryop('UCOMISD')
CVTSI2SD = _binaryop('CVTSI2SD')
CVTTSD2SI = _binaryop('CVTTSD2SI')
+
+ SQRTSD = _binaryop('SQRTSD')
ANDPD = _binaryop('ANDPD')
XORPD = _binaryop('XORPD')
diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py
--- a/pypy/jit/backend/x86/rx86.py
+++ b/pypy/jit/backend/x86/rx86.py
@@ -691,6 +691,8 @@
define_modrm_modes('MOVSD_x*', ['\xF2', rex_nw, '\x0F\x10', register(1,8)], regtype='XMM')
define_modrm_modes('MOVSD_*x', ['\xF2', rex_nw, '\x0F\x11', register(2,8)], regtype='XMM')
+define_modrm_modes('SQRTSD_x*', ['\xF2', rex_nw, '\x0F\x51', register(1,8)], regtype='XMM')
+
#define_modrm_modes('XCHG_r*', [rex_w, '\x87', register(1, 8)])
define_modrm_modes('ADDSD_x*', ['\xF2', rex_nw, '\x0F\x58', register(1, 8)], regtype='XMM')
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -72,6 +72,8 @@
OS_LLONG_UGE = 91
OS_LLONG_URSHIFT = 92
OS_LLONG_FROM_UINT = 93
+ #
+ OS_MATH_SQRT = 100
def __new__(cls, readonly_descrs_fields,
write_descrs_fields, write_descrs_arrays,
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
@@ -351,6 +351,8 @@
prepare = self._handle_jit_call
elif oopspec_name.startswith('libffi_'):
prepare = self._handle_libffi_call
+ elif oopspec_name.startswith('math.sqrt'):
+ prepare = self._handle_math_sqrt_call
else:
prepare = self.prepare_builtin_call
try:
@@ -1360,6 +1362,13 @@
assert vinfo is not None
self.vable_flags[op.args[0]] = op.args[2].value
return []
+
+ # ---------
+ # ll_math.sqrt_nonneg()
+
+ def _handle_math_sqrt_call(self, op, oopspec_name, args):
+ return self._handle_oopspec_call(op, args, EffectInfo.OS_MATH_SQRT,
+ EffectInfo.EF_PURE)
# ____________________________________________________________
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -4,6 +4,7 @@
from pypy.rpython import rlist
from pypy.rpython.lltypesystem import rstr as ll_rstr, rdict as ll_rdict
from pypy.rpython.lltypesystem import rlist as lltypesystem_rlist
+from pypy.rpython.lltypesystem.module import ll_math
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.ootypesystem import rdict as oo_rdict
from pypy.rpython.llinterp import LLInterpreter
@@ -221,6 +222,11 @@
return -x
else:
return x
+
+# math support
+# ------------
+
+_ll_1_ll_math_ll_math_sqrt = ll_math.ll_math_sqrt
# long long support
@@ -388,6 +394,7 @@
('int_mod_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
('int_lshift_ovf', [lltype.Signed, lltype.Signed], lltype.Signed),
('int_abs', [lltype.Signed], lltype.Signed),
+ ('ll_math.ll_math_sqrt', [lltype.Float], lltype.Float),
]
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
@@ -5,6 +5,7 @@
from pypy.jit.codewriter.jtransform import Transformer
from pypy.jit.metainterp.history import getkind
from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rlist
+from pypy.rpython.lltypesystem.module import ll_math
from pypy.translator.unsimplify import varoftype
from pypy.jit.codewriter import heaptracker, effectinfo
from pypy.jit.codewriter.flatten import ListOfKind
@@ -98,7 +99,9 @@
PUNICODE = lltype.Ptr(rstr.UNICODE)
INT = lltype.Signed
UNICHAR = lltype.UniChar
+ FLOAT = lltype.Float
argtypes = {
+ EI.OS_MATH_SQRT: ([FLOAT], FLOAT),
EI.OS_STR2UNICODE:([PSTR], PUNICODE),
EI.OS_STR_CONCAT: ([PSTR, PSTR], PSTR),
EI.OS_STR_SLICE: ([PSTR, INT, INT], PSTR),
@@ -947,3 +950,22 @@
assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_ARRAYCOPY
assert op1.args[2] == ListOfKind('int', [v3, v4, v5])
assert op1.args[3] == ListOfKind('ref', [v1, v2])
+
+def test_math_sqrt():
+ # test that the oopspec is present and correctly transformed
+ FLOAT = lltype.Float
+ FUNC = lltype.FuncType([FLOAT], FLOAT)
+ func = lltype.functionptr(FUNC, 'll_math',
+ _callable=ll_math.sqrt_nonneg)
+ v1 = varoftype(FLOAT)
+ v2 = varoftype(FLOAT)
+ op = SpaceOperation('direct_call', [const(func), v1], v2)
+ tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+ op1 = tr.rewrite_operation(op)
+ assert op1.opname == 'residual_call_irf_f'
+ assert op1.args[0].value == func
+ assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_MATH_SQRT
+ assert op1.args[2] == ListOfKind("int", [])
+ assert op1.args[3] == ListOfKind("ref", [])
+ assert op1.args[4] == ListOfKind('float', [v1])
+ assert op1.result == v2
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -9,6 +9,7 @@
from pypy.jit.metainterp.warmstate import set_future_value
from pypy.jit.codewriter.policy import JitPolicy
from pypy.jit.codewriter import longlong
+from pypy.rlib.rfloat import isinf, isnan
def _get_jitcodes(testself, CPUClass, func, values, type_system,
supports_longlong=False, **kwds):
@@ -181,10 +182,10 @@
result1 = _run_with_blackhole(self, args)
# try to run it with pyjitpl.py
result2 = _run_with_pyjitpl(self, args)
- assert result1 == result2
+ assert result1 == result2 or isnan(result1) and isnan(result2)
# try to run it by running the code compiled just before
result3 = _run_with_machine_code(self, args)
- assert result1 == result3 or result3 == NotImplemented
+ assert result1 == result3 or result3 == NotImplemented or isnan(result1) and isnan(result3)
#
if (longlong.supports_longlong and
isinstance(result1, longlong.r_float_storage)):
diff --git a/pypy/rpython/extfuncregistry.py b/pypy/rpython/extfuncregistry.py
--- a/pypy/rpython/extfuncregistry.py
+++ b/pypy/rpython/extfuncregistry.py
@@ -45,6 +45,9 @@
register_external(math.floor, [float], float,
export_name="ll_math.ll_math_floor", sandboxsafe=True,
llimpl=ll_math.ll_math_floor)
+register_external(math.sqrt, [float], float,
+ export_name="ll_math.ll_math_sqrt", sandboxsafe=True,
+ llimpl=ll_math.ll_math_sqrt)
complex_math_functions = [
('frexp', [float], (float, int)),
diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -9,7 +9,7 @@
from pypy.rlib import jit, rposix
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.translator.platform import platform
-from pypy.rlib.rfloat import isinf, isnan, INFINITY, NAN
+from pypy.rlib.rfloat import isfinite, isinf, isnan, INFINITY, NAN
if sys.platform == "win32":
if platform.name == "msvc":
@@ -69,6 +69,13 @@
[rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
math_floor = llexternal('floor', [rffi.DOUBLE], rffi.DOUBLE, pure_function=True)
+math_sqrt = llexternal('sqrt', [rffi.DOUBLE], rffi.DOUBLE)
+
+ at jit.purefunction
+def sqrt_nonneg(x):
+ return math_sqrt(x)
+sqrt_nonneg.oopspec = "math.sqrt_nonneg(x)"
+
# ____________________________________________________________
#
# Error handling functions
@@ -319,6 +326,15 @@
_likely_raise(errno, r)
return r
+def ll_math_sqrt(x):
+ if x < 0.0:
+ raise ValueError, "math domain error"
+
+ if isfinite(x):
+ return sqrt_nonneg(x)
+
+ return x # +inf or nan
+
# ____________________________________________________________
#
# Default implementations
@@ -357,7 +373,7 @@
unary_math_functions = [
'acos', 'asin', 'atan',
'ceil', 'cos', 'cosh', 'exp', 'fabs',
- 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'log', 'log10',
+ 'sin', 'sinh', 'tan', 'tanh', 'log', 'log10',
'acosh', 'asinh', 'atanh', 'log1p', 'expm1',
]
unary_math_functions_can_overflow = [
From commits-noreply at bitbucket.org Sat May 7 12:49:27 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sat, 7 May 2011 12:49:27 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Adapt the _immutable_
and _immutable_fields_ hints left and right.
Message-ID: <20110507104927.C316B2A2035@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43936:98ad343ba2a4
Date: 2011-05-07 10:09 +0000
http://bitbucket.org/pypy/pypy/changeset/98ad343ba2a4/
Log: Adapt the _immutable_ and _immutable_fields_ hints left and right. I
think this branch is now ready to be merged, if it passes all tests.
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1266,10 +1266,11 @@
class FrameBlock(object):
-
"""Abstract base class for frame blocks from the blockstack,
used by the SETUP_XXX and POP_BLOCK opcodes."""
+ _immutable_ = True
+
def __init__(self, frame, handlerposition):
self.handlerposition = handlerposition
self.valuestackdepth = frame.valuestackdepth
@@ -1311,6 +1312,7 @@
class LoopBlock(FrameBlock):
"""A loop block. Stores the end-of-loop pointer in case of 'break'."""
+ _immutable_ = True
_opname = 'SETUP_LOOP'
handling_mask = SBreakLoop.kind | SContinueLoop.kind
@@ -1330,6 +1332,7 @@
class ExceptBlock(FrameBlock):
"""An try:except: block. Stores the position of the exception handler."""
+ _immutable_ = True
_opname = 'SETUP_EXCEPT'
handling_mask = SApplicationException.kind
@@ -1354,6 +1357,7 @@
class FinallyBlock(FrameBlock):
"""A try:finally: block. Stores the position of the exception handler."""
+ _immutable_ = True
_opname = 'SETUP_FINALLY'
handling_mask = -1 # handles every kind of SuspendedUnroller
@@ -1381,6 +1385,8 @@
class WithBlock(FinallyBlock):
+ _immutable_ = True
+
def really_handle(self, frame, unroller):
if (frame.space.full_exceptions and
isinstance(unroller, SApplicationException)):
diff --git a/pypy/interpreter/special.py b/pypy/interpreter/special.py
--- a/pypy/interpreter/special.py
+++ b/pypy/interpreter/special.py
@@ -2,14 +2,12 @@
from pypy.interpreter.baseobjspace import Wrappable
class Ellipsis(Wrappable):
- _immutable_ = True
def __init__(self, space):
self.space = space
def descr__repr__(self):
return self.space.wrap('Ellipsis')
class NotImplemented(Wrappable):
- _immutable_ = True
def __init__(self, space):
self.space = space
def descr__repr__(self):
diff --git a/pypy/objspace/std/boolobject.py b/pypy/objspace/std/boolobject.py
--- a/pypy/objspace/std/boolobject.py
+++ b/pypy/objspace/std/boolobject.py
@@ -5,8 +5,7 @@
class W_BoolObject(W_Object):
from pypy.objspace.std.booltype import bool_typedef as typedef
-
- _immutable_ = True
+ _immutable_fields_ = ['boolval']
def __init__(w_self, boolval):
w_self.boolval = not not boolval
diff --git a/pypy/objspace/std/noneobject.py b/pypy/objspace/std/noneobject.py
--- a/pypy/objspace/std/noneobject.py
+++ b/pypy/objspace/std/noneobject.py
@@ -9,7 +9,6 @@
class W_NoneObject(W_Object):
from pypy.objspace.std.nonetype import none_typedef as typedef
- _immutable_ = True
def unwrap(w_self, space):
return None
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -88,7 +88,7 @@
_immutable_fields_ = ["flag_heaptype",
"flag_cpytype",
- # flag_abstract is not immutable
+ "flag_abstract?",
'needsdel',
'weakrefable',
'hasdict',
From commits-noreply at bitbucket.org Sat May 7 12:53:59 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sat, 7 May 2011 12:53:59 +0200 (CEST)
Subject: [pypy-svn] pypy default: Remove external reference to codespeak
Message-ID: <20110507105359.BBAFB2A2035@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43937:a53ca6da4baf
Date: 2011-05-07 12:20 +0200
http://bitbucket.org/pypy/pypy/changeset/a53ca6da4baf/
Log: Remove external reference to codespeak
diff --git a/pypy/doc/_ref.txt b/pypy/doc/_ref.txt
--- a/pypy/doc/_ref.txt
+++ b/pypy/doc/_ref.txt
@@ -1,3 +1,4 @@
+.. _`ctypes_configure/doc/sample.py`: https://bitbucket.org/pypy/pypy/src/default/ctypes_configure/doc/sample.py
.. _`demo/`: https://bitbucket.org/pypy/pypy/src/default/demo/
.. _`demo/pickle_coroutine.py`: https://bitbucket.org/pypy/pypy/src/default/demo/pickle_coroutine.py
.. _`lib-python/`: https://bitbucket.org/pypy/pypy/src/default/lib-python/
diff --git a/pypy/doc/ctypes-implementation.rst b/pypy/doc/ctypes-implementation.rst
--- a/pypy/doc/ctypes-implementation.rst
+++ b/pypy/doc/ctypes-implementation.rst
@@ -137,7 +137,27 @@
ctypes configure
=================
-We also released `ctypes-configure`_, which is an experimental package trying to
-approach the portability issues of ctypes-based code.
+We also released ``ctypes-configure``, which is an experimental package
+trying to approach the portability issues of ctypes-based code.
-.. _`ctypes-configure`: http://codespeak.net/~fijal/configure.html
+idea
+----
+
+One of ctypes problems is that ctypes programs are usually not very
+platform-independent. We created ctypes_configure, which invokes c
+compiler (via distutils) for various platform-dependent details like
+exact sizes of types (for example size_t), ``#defines``, exact outline of
+structures etc. It replaces in this regard code generator (h2py).
+
+installation
+------------
+
+``easy_install ctypes_configure``
+
+usage
+-----
+
+`ctypes_configure/doc/sample.py`_ explains in details how to use it.
+
+
+.. include:: _ref.txt
From commits-noreply at bitbucket.org Sat May 7 12:54:00 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sat, 7 May 2011 12:54:00 +0200 (CEST)
Subject: [pypy-svn] pypy default: Remove some more codespeak dependencies.
Message-ID: <20110507105400.D9F1B2A2035@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43938:e9e7c0edadb6
Date: 2011-05-07 12:40 +0200
http://bitbucket.org/pypy/pypy/changeset/e9e7c0edadb6/
Log: Remove some more codespeak dependencies.
diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst
--- a/pypy/doc/extending.rst
+++ b/pypy/doc/extending.rst
@@ -42,7 +42,7 @@
platform-dependent details (compiling small snippets of C code and running
them), so it'll benefit not pypy-related ctypes-based modules as well.
-.. _`ctypes-configure`: http://codespeak.net/~fijal/configure.html
+.. _`ctypes-configure`: ctypes-implementation.html#ctypes-configure
Pros
----
diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -300,6 +300,6 @@
.. _`CLI backend`: cli-backend.html
.. _`Boehm-Demers-Weiser garbage collector`: http://www.hpl.hp.com/personal/Hans_Boehm/gc/
.. _clr: clr-module.html
-.. _`CPythons core language regression tests`: http://codespeak.net:8099/summary?category=applevel&branch=%3Ctrunk%3E
+.. _`CPythons core language regression tests`: http://buildbot.pypy.org/summary?category=applevel&branch=%3Ctrunk%3E
.. include:: _ref.txt
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -141,15 +141,6 @@
You can also find CPython's compliance tests run with compiled ``pypy-c``
executables there.
-information dating from early 2007:
-
-`PyPy LOC statistics`_ shows LOC statistics about PyPy.
-
-`PyPy statistics`_ is a page with various statistics about the PyPy project.
-
-`compatibility matrix`_ is a diagram that shows which of the various features
-of the PyPy interpreter work together with which other features.
-
Source Code Documentation
===============================================
@@ -207,8 +198,6 @@
.. _`development methodology`: dev_method.html
.. _`sprint reports`: sprint-reports.html
.. _`papers, talks and related projects`: extradoc.html
-.. _`PyPy LOC statistics`: http://codespeak.net/~hpk/pypy-stat/
-.. _`PyPy statistics`: http://codespeak.net/pypy/trunk/pypy/doc/statistic
.. _`object spaces`: objspace.html
.. _`interpreter optimizations`: interpreter-optimizations.html
.. _`translation`: translation.html
@@ -222,7 +211,7 @@
.. _`bytecode interpreter`: interpreter.html
.. _`EU reports`: index-report.html
.. _`Technical reports`: index-report.html
-.. _`summary`: http://codespeak.net:8099/summary
+.. _`summary`: http://buildbot.pypy.org/summary
.. _`ideas for PyPy related projects`: project-ideas.html
.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html
.. _`directory reference`:
@@ -360,7 +349,6 @@
.. _Mono: http://www.mono-project.com/
.. _`"standard library"`: rlib.html
.. _`graph viewer`: getting-started-dev.html#try-out-the-translator
-.. _`compatibility matrix`: image/compat-matrix.png
.. The following documentation is important and reasonably up-to-date:
From commits-noreply at bitbucket.org Sat May 7 12:54:03 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sat, 7 May 2011 12:54:03 +0200 (CEST)
Subject: [pypy-svn] pypy default: The torrents are set up on wyvern for now,
but writing explicit
Message-ID: <20110507105403.3ACF22A203A@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43939:6359f7f95dd3
Date: 2011-05-07 12:51 +0200
http://bitbucket.org/pypy/pypy/changeset/6359f7f95dd3/
Log: The torrents are set up on wyvern for now, but writing explicit
wyvern urls is probably wrong.
diff --git a/pypy/doc/video-index.rst b/pypy/doc/video-index.rst
--- a/pypy/doc/video-index.rst
+++ b/pypy/doc/video-index.rst
@@ -42,11 +42,11 @@
Trailer: PyPy at the PyCon 2006
-------------------------------
-130mb: http://codespeak.net/download/pypy/video/pycon-trailer.avi.torrent
+130mb: http://wyvern.cs.uni-duesseldorf.de/torrent/pycon-trailer.avi.torrent
-71mb: http://codespeak.net/download/pypy/video/pycon-trailer-medium.avi.torrent
+71mb: http://wyvern.cs.uni-duesseldorf.de/torrent/pycon-trailer-medium.avi.torrent
-50mb: http://codespeak.net/download/pypy/video/pycon-trailer-320x240.avi.torrent
+50mb: http://wyvern.cs.uni-duesseldorf.de/torrent/pycon-trailer-320x240.avi.torrent
.. image:: image/pycon-trailer.jpg
:scale: 100
@@ -62,9 +62,9 @@
Interview with Tim Peters
-------------------------
-440mb: http://codespeak.net/download/pypy/video/interview-timpeters-v2.avi.torrent
+440mb: http://wyvern.cs.uni-duesseldorf.de/torrent/interview-timpeters-v2.avi.torrent
-138mb: http://codespeak.net/download/pypy/video/interview-timpeters-320x240.avi.torrent
+138mb: http://wyvern.cs.uni-duesseldorf.de/torrent/interview-timpeters-320x240.avi.torrent
.. image:: image/interview-timpeters.jpg
:scale: 100
@@ -82,9 +82,9 @@
Interview with Bob Ippolito
---------------------------
-155mb: http://codespeak.net/download/pypy/video/interview-bobippolito-v2.avi.torrent
+155mb: http://wyvern.cs.uni-duesseldorf.de/torrent/interview-bobippolito-v2.avi.torrent
-50mb: http://codespeak.net/download/pypy/video/interview-bobippolito-320x240.avi.torrent
+50mb: http://wyvern.cs.uni-duesseldorf.de/torrent/interview-bobippolito-320x240.avi.torrent
.. image:: image/interview-bobippolito.jpg
:scale: 100
@@ -102,9 +102,9 @@
Introductory talk on PyPy
-------------------------
-430mb: http://codespeak.net/download/pypy/video/introductory-talk-pycon-v1.avi.torrent
+430mb: http://wyvern.cs.uni-duesseldorf.de/torrent/introductory-talk-pycon-v1.avi.torrent
-166mb: http://codespeak.net/download/pypy/video/introductory-talk-pycon-320x240.avi.torrent
+166mb: http://wyvern.cs.uni-duesseldorf.de/torrent/introductory-talk-pycon-320x240.avi.torrent
.. image:: image/introductory-talk-pycon.jpg
:scale: 100
@@ -125,9 +125,9 @@
Talk on Agile Open Source Methods in the PyPy project
-----------------------------------------------------
-395mb: http://codespeak.net/download/pypy/video/agile-talk-v1.avi.torrent
+395mb: http://wyvern.cs.uni-duesseldorf.de/torrent/agile-talk-v1.avi.torrent
-153mb: http://codespeak.net/download/pypy/video/agile-talk-320x240.avi.torrent
+153mb: http://wyvern.cs.uni-duesseldorf.de/torrent/agile-talk-320x240.avi.torrent
.. image:: image/agile-talk.jpg
:scale: 100
@@ -148,9 +148,9 @@
PyPy Architecture session
-------------------------
-744mb: http://codespeak.net/download/pypy/video/architecture-session-v1.avi.torrent
+744mb: http://wyvern.cs.uni-duesseldorf.de/torrent/architecture-session-v1.avi.torrent
-288mb: http://codespeak.net/download/pypy/video/architecture-session-320x240.avi.torrent
+288mb: http://wyvern.cs.uni-duesseldorf.de/torrent/architecture-session-320x240.avi.torrent
.. image:: image/architecture-session.jpg
:scale: 100
@@ -171,9 +171,9 @@
Sprint tutorial
---------------
-680mb: http://codespeak.net/download/pypy/video/sprint-tutorial-v2.avi.torrent
+680mb: http://wyvern.cs.uni-duesseldorf.de/torrent/sprint-tutorial-v2.avi.torrent
-263mb: http://codespeak.net/download/pypy/video/sprint-tutorial-320x240.avi.torrent
+263mb: http://wyvern.cs.uni-duesseldorf.de/torrent/sprint-tutorial-320x240.avi.torrent
.. image:: image/sprint-tutorial.jpg
:scale: 100
@@ -190,9 +190,9 @@
Scripting .NET with IronPython by Jim Hugunin
---------------------------------------------
-372mb: http://codespeak.net/download/pypy/video/ironpython-talk-v2.avi.torrent
+372mb: http://wyvern.cs.uni-duesseldorf.de/torrent/ironpython-talk-v2.avi.torrent
-270mb: http://codespeak.net/download/pypy/video/ironpython-talk-320x240.avi.torrent
+270mb: http://wyvern.cs.uni-duesseldorf.de/torrent/ironpython-talk-320x240.avi.torrent
.. image:: image/ironpython.jpg
:scale: 100
@@ -209,9 +209,9 @@
Bram Cohen, founder and developer of BitTorrent
-----------------------------------------------
-509mb: http://codespeak.net/download/pypy/video/bram-cohen-interview-v1.avi.torrent
+509mb: http://wyvern.cs.uni-duesseldorf.de/torrent/bram-cohen-interview-v1.avi.torrent
-370mb: http://codespeak.net/download/pypy/video/bram-cohen-interview-320x240.avi.torrent
+370mb: http://wyvern.cs.uni-duesseldorf.de/torrent/bram-cohen-interview-320x240.avi.torrent
.. image:: image/bram.jpg
:scale: 100
@@ -226,9 +226,9 @@
Keynote speech by Guido van Rossum on the new Python 2.5 features
-----------------------------------------------------------------
-695mb: http://codespeak.net/download/pypy/video/keynote-speech_guido-van-rossum_v1.avi.torrent
+695mb: http://wyvern.cs.uni-duesseldorf.de/torrent/keynote-speech_guido-van-rossum_v1.avi.torrent
-430mb: http://codespeak.net/download/pypy/video/keynote-speech_guido-van-rossum_320x240.avi.torrent
+430mb: http://wyvern.cs.uni-duesseldorf.de/torrent/keynote-speech_guido-van-rossum_320x240.avi.torrent
.. image:: image/guido.jpg
:scale: 100
@@ -243,11 +243,11 @@
Trailer: PyPy sprint at the University of Palma de Mallorca
-----------------------------------------------------------
-166mb: http://codespeak.net/download/pypy/video/mallorca-trailer-v1.avi.torrent
+166mb: http://wyvern.cs.uni-duesseldorf.de/torrent/mallorca-trailer-v1.avi.torrent
-88mb: http://codespeak.net/download/pypy/video/mallorca-trailer-medium.avi.torrent
+88mb: http://wyvern.cs.uni-duesseldorf.de/torrent/mallorca-trailer-medium.avi.torrent
-64mb: http://codespeak.net/download/pypy/video/mallorca-trailer-320x240.avi.torrent
+64mb: http://wyvern.cs.uni-duesseldorf.de/torrent/mallorca-trailer-320x240.avi.torrent
.. image:: image/mallorca-trailer.jpg
:scale: 100
@@ -262,9 +262,9 @@
Coding discussion of core developers Armin Rigo and Samuele Pedroni
-------------------------------------------------------------------
-620mb: http://codespeak.net/download/pypy/video/coding-discussion-v1.avi.torrent
+620mb: http://wyvern.cs.uni-duesseldorf.de/torrent/coding-discussion-v1.avi.torrent
-240mb: http://codespeak.net/download/pypy/video/coding-discussion-320x240.avi.torrent
+240mb: http://wyvern.cs.uni-duesseldorf.de/torrent/coding-discussion-320x240.avi.torrent
.. image:: image/coding-discussion.jpg
:scale: 100
@@ -279,9 +279,9 @@
PyPy technical talk at the University of Palma de Mallorca
----------------------------------------------------------
-865mb: http://codespeak.net/download/pypy/video/introductory-student-talk-v2.avi.torrent
+865mb: http://wyvern.cs.uni-duesseldorf.de/torrent/introductory-student-talk-v2.avi.torrent
-437mb: http://codespeak.net/download/pypy/video/introductory-student-talk-320x240.avi.torrent
+437mb: http://wyvern.cs.uni-duesseldorf.de/torrent/introductory-student-talk-320x240.avi.torrent
.. image:: image/introductory-student-talk.jpg
:scale: 100
From commits-noreply at bitbucket.org Sat May 7 15:58:56 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sat, 7 May 2011 15:58:56 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Fix.
Message-ID: <20110507135856.73C2C36C201@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43940:a44729d56030
Date: 2011-05-07 15:58 +0200
http://bitbucket.org/pypy/pypy/changeset/a44729d56030/
Log: Fix.
diff --git a/pypy/jit/tool/jitoutput.py b/pypy/jit/tool/jitoutput.py
--- a/pypy/jit/tool/jitoutput.py
+++ b/pypy/jit/tool/jitoutput.py
@@ -25,6 +25,7 @@
(('abort.compiling',), '^abort: compiling:\s+(\d+)$'),
(('abort.vable_escape',), '^abort: vable escape:\s+(\d+)$'),
(('abort.bad_loop',), '^abort: bad loop:\s+(\d+)$'),
+ (('abort.force_quasiimmut',), '^abort: force quasi-immut:\s+(\d+)$'),
(('nvirtuals',), '^nvirtuals:\s+(\d+)$'),
(('nvholes',), '^nvholes:\s+(\d+)$'),
(('nvreused',), '^nvreused:\s+(\d+)$'),
diff --git a/pypy/jit/tool/test/test_jitoutput.py b/pypy/jit/tool/test/test_jitoutput.py
--- a/pypy/jit/tool/test/test_jitoutput.py
+++ b/pypy/jit/tool/test/test_jitoutput.py
@@ -61,6 +61,7 @@
abort: compiling: 11
abort: vable escape: 12
abort: bad loop: 135
+abort: force quasi-immut: 3
nvirtuals: 13
nvholes: 14
nvreused: 15
@@ -89,6 +90,7 @@
assert info.abort.compiling == 11
assert info.abort.vable_escape == 12
assert info.abort.bad_loop == 135
+ assert info.abort.force_quasiimmut == 3
assert info.nvirtuals == 13
assert info.nvholes == 14
assert info.nvreused == 15
From commits-noreply at bitbucket.org Sun May 8 12:32:58 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 12:32:58 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: Fix test.
Message-ID: <20110508103258.04A082A2036@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43941:20aac7a986d5
Date: 2011-05-07 16:01 +0200
http://bitbucket.org/pypy/pypy/changeset/20aac7a986d5/
Log: Fix test.
diff --git a/pypy/module/pypyjit/test_pypy_c/test_model.py b/pypy/module/pypyjit/test_pypy_c/test_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_model.py
@@ -468,11 +468,13 @@
log = self.run(f)
loop, = log.loops_by_id('ntohs')
assert loop.match_by_id('ntohs', """
+ guard_not_invalidated(descr=...)
p12 = call(ConstClass(ntohs), 1, descr=...)
guard_no_exception(descr=...)
""")
#
assert not loop.match_by_id('ntohs', """
+ guard_not_invalidated(descr=...)
p12 = call(ConstClass(foobar), 1, descr=...)
guard_no_exception(descr=...)
""")
From commits-noreply at bitbucket.org Sun May 8 12:33:00 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 12:33:00 +0200 (CEST)
Subject: [pypy-svn] pypy default: Obscure workaround for cpyext. Fixes
test_structseq.py, which
Message-ID: <20110508103300.12A622A2039@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43942:2b4ea6060860
Date: 2011-05-08 12:32 +0200
http://bitbucket.org/pypy/pypy/changeset/2b4ea6060860/
Log: Obscure workaround for cpyext. Fixes test_structseq.py, which has
been failing since 6ee045ccb063. Blame new-dict-proxy devs for not
running tests before merging...
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -304,7 +304,12 @@
self.unimport_module(name)
self.cleanup_references(self.space)
if self.check_and_print_leaks():
- assert False, "Test leaks or loses object(s)."
+ assert False, (
+ "Test leaks or loses object(s). You should also check if "
+ "the test actually passed in the first place; if it failed "
+ "it is likely to reach this place.")
+ # XXX find out how to disable check_and_print_leaks() if the
+ # XXX test failed...
class AppTestCpythonExtension(AppTestCpythonExtensionBase):
diff --git a/pypy/module/cpyext/test/test_structseq.py b/pypy/module/cpyext/test/test_structseq.py
--- a/pypy/module/cpyext/test/test_structseq.py
+++ b/pypy/module/cpyext/test/test_structseq.py
@@ -30,6 +30,7 @@
"""
PyObject *seq;
PyStructSequence_InitType(&PyDatatype, &Data_desc);
+ if (PyErr_Occurred()) return NULL;
seq = PyStructSequence_New(&PyDatatype);
if (!seq) return NULL;
PyStructSequence_SET_ITEM(seq, 0, PyInt_FromLong(42));
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -29,7 +29,18 @@
raise OperationError(space.w_TypeError, space.wrap("cannot add non-string keys to dict of a type"))
def impl_setitem_str(self, name, w_value):
- self.w_type.setdictvalue(self.space, name, w_value)
+ try:
+ self.w_type.setdictvalue(self.space, name, w_value)
+ except OperationError, e:
+ if not e.match(self.space, self.space.w_TypeError):
+ raise
+ w_type = self.w_type
+ if not w_type.is_cpytype():
+ raise
+ # xxx obscure workaround: allow cpyext to write to type->tp_dict.
+ # xxx like CPython, we assume that this is only done early after
+ # xxx the type is created, and we don't invalidate any cache.
+ w_type.dict_w[name] = w_value
def impl_setdefault(self, w_key, w_default):
space = self.space
From commits-noreply at bitbucket.org Sun May 8 12:56:58 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 12:56:58 +0200 (CEST)
Subject: [pypy-svn] pypy default: More obscurity in the behavior of sets. It
seems that in order
Message-ID: <20110508105658.71C432A2036@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43943:6faba9397a0b
Date: 2011-05-08 12:56 +0200
http://bitbucket.org/pypy/pypy/changeset/6faba9397a0b/
Log: More obscurity in the behavior of sets. It seems that in order to
make new *frozen* sets, their possibly overridden __new__ must be
called; but to make new *non-frozen* sets, it must not.
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -32,22 +32,6 @@
reprlist = [repr(w_item) for w_item in w_self.setdata.keys()]
return "<%s(%s)>" % (w_self.__class__.__name__, ', '.join(reprlist))
- def _newobj(w_self, space, rdict_w=None):
- """Make a new set or frozenset by taking ownership of 'rdict_w'."""
- #return space.call(space.type(w_self),W_SetIterObject(rdict_w))
- objtype = type(w_self)
- if objtype is W_SetObject:
- w_obj = W_SetObject(space, rdict_w)
- elif objtype is W_FrozensetObject:
- w_obj = W_FrozensetObject(space, rdict_w)
- else:
- w_type = space.type(w_self)
- _, w_newdescr = w_type.lookup_where('__new__')
- w_newfunc = space.get(w_newdescr, w_type)
- w_itemiterator = W_SetIterObject(rdict_w)
- w_obj = space.call_function(w_newfunc, w_type, w_itemiterator)
- return w_obj
-
_lifeline_ = None
def getweakref(self):
return self._lifeline_
@@ -57,10 +41,29 @@
class W_SetObject(W_BaseSetObject):
from pypy.objspace.std.settype import set_typedef as typedef
+ def _newobj(w_self, space, rdict_w):
+ """Make a new set by taking ownership of 'rdict_w'."""
+ if type(w_self) is W_SetObject:
+ return W_SetObject(space, rdict_w)
+ w_type = space.type(w_self)
+ w_obj = space.allocate_instance(W_SetObject, w_type)
+ W_SetObject.__init__(w_obj, space, rdict_w)
+ return w_obj
+
class W_FrozensetObject(W_BaseSetObject):
from pypy.objspace.std.frozensettype import frozenset_typedef as typedef
hash = 0
+ def _newobj(w_self, space, rdict_w):
+ """Make a new frozenset by taking ownership of 'rdict_w'."""
+ if type(w_self) is W_FrozensetObject:
+ return W_FrozensetObject(space, rdict_w)
+ w_type = space.type(w_self)
+ _, w_newdescr = w_type.lookup_where('__new__')
+ w_newfunc = space.get(w_newdescr, w_type)
+ w_itemiterator = W_SetIterObject(rdict_w)
+ return space.call_function(w_newfunc, w_type, w_itemiterator)
+
registerimplementation(W_BaseSetObject)
registerimplementation(W_SetObject)
registerimplementation(W_FrozensetObject)
diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py
--- a/pypy/objspace/std/test/test_setobject.py
+++ b/pypy/objspace/std/test/test_setobject.py
@@ -57,6 +57,23 @@
b = a | set('abc')
assert type(b) is subset
+ def test_init_new_behavior(self):
+ s = set.__new__(set, 'abc')
+ assert s == set() # empty
+ s.__init__('def')
+ assert s == set('def')
+ #
+ s = frozenset.__new__(frozenset, 'abc')
+ assert s == frozenset('abc') # non-empty
+ s.__init__('def')
+ assert s == frozenset('abc') # the __init__ is ignored
+
+ def test_subtype_bug(self):
+ class subset(set):pass
+ b = subset('abc').copy()
+ assert type(b) is subset
+ assert set(b) == set('abc')
+
def test_union(self):
a = set([4, 5])
b = a.union([5, 7])
From commits-noreply at bitbucket.org Sun May 8 13:00:25 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 13:00:25 +0200 (CEST)
Subject: [pypy-svn] pypy default: Wrong. A test was present but failed on
CPython 2.7 (with -A).
Message-ID: <20110508110025.CA1762A2036@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43944:9ccaeaff6e07
Date: 2011-05-08 13:00 +0200
http://bitbucket.org/pypy/pypy/changeset/9ccaeaff6e07/
Log: Wrong. A test was present but failed on CPython 2.7 (with -A).
Killed it, and replaced it with tests that check that even when
making new frozen sets, the overridden __new__ is not called.
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -59,10 +59,9 @@
if type(w_self) is W_FrozensetObject:
return W_FrozensetObject(space, rdict_w)
w_type = space.type(w_self)
- _, w_newdescr = w_type.lookup_where('__new__')
- w_newfunc = space.get(w_newdescr, w_type)
- w_itemiterator = W_SetIterObject(rdict_w)
- return space.call_function(w_newfunc, w_type, w_itemiterator)
+ w_obj = space.allocate_instance(W_FrozensetObject, w_type)
+ W_FrozensetObject.__init__(w_obj, space, rdict_w)
+ return w_obj
registerimplementation(W_BaseSetObject)
registerimplementation(W_SetObject)
diff --git a/pypy/objspace/std/test/test_setobject.py b/pypy/objspace/std/test/test_setobject.py
--- a/pypy/objspace/std/test/test_setobject.py
+++ b/pypy/objspace/std/test/test_setobject.py
@@ -69,10 +69,19 @@
assert s == frozenset('abc') # the __init__ is ignored
def test_subtype_bug(self):
- class subset(set):pass
- b = subset('abc').copy()
+ class subset(set): pass
+ b = subset('abc')
+ subset.__new__ = lambda *args: foobar # not called
+ b = b.copy()
assert type(b) is subset
assert set(b) == set('abc')
+ #
+ class frozensubset(frozenset): pass
+ b = frozensubset('abc')
+ frozensubset.__new__ = lambda *args: foobar # not called
+ b = b.copy()
+ assert type(b) is frozensubset
+ assert frozenset(b) == frozenset('abc')
def test_union(self):
a = set([4, 5])
@@ -148,11 +157,6 @@
assert s1 is not s2
assert s1 == s2
assert type(s2) is myfrozen
- class myfrozen(frozenset):
- def __new__(cls):
- return frozenset.__new__(cls, 'abc')
- s1 = myfrozen()
- raises(TypeError, s1.copy)
def test_update(self):
s1 = set('abc')
From commits-noreply at bitbucket.org Sun May 8 16:01:31 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 16:01:31 +0200 (CEST)
Subject: [pypy-svn] pypy default: hg merge out-of-line-guards-2
Message-ID: <20110508140131.2BB3B2A2036@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43945:98d5562c9322
Date: 2011-05-08 15:46 +0200
http://bitbucket.org/pypy/pypy/changeset/98d5562c9322/
Log: hg merge out-of-line-guards-2
diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py
--- a/pypy/annotation/description.py
+++ b/pypy/annotation/description.py
@@ -3,7 +3,6 @@
from pypy.interpreter.pycode import cpython_code_signature
from pypy.interpreter.argument import rawshape
from pypy.interpreter.argument import ArgErr
-from pypy.interpreter.function import Defaults
from pypy.tool.sourcetools import valid_identifier
from pypy.tool.pairtype import extendabletype
@@ -251,7 +250,7 @@
for x in defaults:
defs_s.append(self.bookkeeper.immutablevalue(x))
try:
- inputcells = args.match_signature(signature, Defaults(defs_s))
+ inputcells = args.match_signature(signature, defs_s)
except ArgErr, e:
raise TypeError, "signature mismatch: %s" % e.getmsg(self.name)
return inputcells
@@ -638,16 +637,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
@@ -3398,6 +3398,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/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -239,7 +239,7 @@
### Parsing for function calls ###
- def _match_signature(self, w_firstarg, scope_w, signature, defaults=None,
+ def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=None,
blindargs=0):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
@@ -247,20 +247,20 @@
"""
if jit.we_are_jitted() and self._dont_jit:
return self._match_signature_jit_opaque(w_firstarg, scope_w,
- signature, defaults,
+ signature, defaults_w,
blindargs)
return self._really_match_signature(w_firstarg, scope_w, signature,
- defaults, blindargs)
+ defaults_w, blindargs)
@jit.dont_look_inside
def _match_signature_jit_opaque(self, w_firstarg, scope_w, signature,
- defaults, blindargs):
+ defaults_w, blindargs):
return self._really_match_signature(w_firstarg, scope_w, signature,
- defaults, blindargs)
+ defaults_w, blindargs)
@jit.unroll_safe
- def _really_match_signature(self, w_firstarg, scope_w, signature, defaults=None,
- blindargs=0):
+ def _really_match_signature(self, w_firstarg, scope_w, signature,
+ defaults_w=None, blindargs=0):
#
# args_w = list of the normal actual parameters, wrapped
# kwds_w = real dictionary {'keyword': wrapped parameter}
@@ -327,7 +327,7 @@
elif avail > co_argcount:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults, 0)
+ defaults_w, 0)
# the code assumes that keywords can potentially be large, but that
# argnames is typically not too large
@@ -357,12 +357,13 @@
num_remainingkwds -= 1
missing = 0
if input_argcount < co_argcount:
- def_first = co_argcount - (0 if defaults is None else defaults.getlen())
+ def_first = co_argcount - (0 if defaults_w is None else len(defaults_w))
for i in range(input_argcount, co_argcount):
if scope_w[i] is not None:
- pass
- elif i >= def_first:
- scope_w[i] = defaults.getitem(i - def_first)
+ continue
+ defnum = i - def_first
+ if defnum >= 0:
+ scope_w[i] = defaults_w[defnum]
else:
# error: not enough arguments. Don't signal it immediately
# because it might be related to a problem with */** or
@@ -382,20 +383,20 @@
if co_argcount == 0:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults, missing)
+ defaults_w, missing)
raise ArgErrUnknownKwds(num_remainingkwds, keywords, used_keywords)
if missing:
raise ArgErrCount(avail, num_kwds,
co_argcount, has_vararg, has_kwarg,
- defaults, missing)
+ defaults_w, missing)
return co_argcount + has_vararg + has_kwarg
def parse_into_scope(self, w_firstarg,
- scope_w, fnname, signature, defaults=None):
+ scope_w, fnname, signature, defaults_w=None):
"""Parse args and kwargs to initialize a frame
according to the signature of code object.
Store the argumentvalues into scope_w.
@@ -403,29 +404,29 @@
"""
try:
return self._match_signature(w_firstarg,
- scope_w, signature, defaults, 0)
+ scope_w, signature, defaults_w, 0)
except ArgErr, e:
raise OperationError(self.space.w_TypeError,
self.space.wrap(e.getmsg(fnname)))
- def _parse(self, w_firstarg, signature, defaults, blindargs=0):
+ def _parse(self, w_firstarg, signature, defaults_w, blindargs=0):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
"""
scopelen = signature.scope_length()
scope_w = [None] * scopelen
- self._match_signature(w_firstarg, scope_w, signature, defaults,
+ self._match_signature(w_firstarg, scope_w, signature, defaults_w,
blindargs)
return scope_w
def parse_obj(self, w_firstarg,
- fnname, signature, defaults=None, blindargs=0):
+ fnname, signature, defaults_w=None, blindargs=0):
"""Parse args and kwargs to initialize a frame
according to the signature of code object.
"""
try:
- return self._parse(w_firstarg, signature, defaults, blindargs)
+ return self._parse(w_firstarg, signature, defaults_w, blindargs)
except ArgErr, e:
raise OperationError(self.space.w_TypeError,
self.space.wrap(e.getmsg(fnname)))
@@ -474,23 +475,23 @@
- def _match_signature(self, w_firstarg, scope_w, signature, defaults=None,
+ def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=None,
blindargs=0):
self.combine_if_necessary()
# _match_signature is destructive
return Arguments._match_signature(
self, w_firstarg, scope_w, signature,
- defaults, blindargs)
+ defaults_w, blindargs)
def unpack(self):
self.combine_if_necessary()
return Arguments.unpack(self)
- def match_signature(self, signature, defaults):
+ def match_signature(self, signature, defaults_w):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
"""
- return self._parse(None, signature, defaults)
+ return self._parse(None, signature, defaults_w)
def unmatch_signature(self, signature, data_w):
"""kind of inverse of match_signature"""
@@ -603,12 +604,12 @@
class ArgErrCount(ArgErr):
def __init__(self, got_nargs, nkwds, expected_nargs, has_vararg, has_kwarg,
- defaults, missing_args):
+ defaults_w, missing_args):
self.expected_nargs = expected_nargs
self.has_vararg = has_vararg
self.has_kwarg = has_kwarg
- self.num_defaults = 0 if defaults is None else defaults.getlen()
+ self.num_defaults = 0 if defaults_w is None else len(defaults_w)
self.missing_args = missing_args
self.num_args = got_nargs
self.num_kwds = nkwds
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -21,28 +21,6 @@
assert not func.can_change_code
return func.code
-class Defaults(object):
- _immutable_fields_ = ["items[*]", "promote"]
-
- def __init__(self, items, promote=False):
- self.items = items
- self.promote = promote
-
- def getitems(self):
- # an idea - we want to promote only items that we know won't change
- # too often. this is the case for builtin functions and functions
- # with known constant defaults. Otherwise we don't want to promote
- # this so lambda a=a won't create a new trace each time it's
- # encountered
- if self.promote:
- return jit.hint(self, promote=True).items
- return self.items
-
- def getitem(self, idx):
- return self.getitems()[idx]
-
- def getlen(self):
- return len(self.getitems())
class Function(Wrappable):
"""A function is a code object captured with some environment:
@@ -50,17 +28,20 @@
and an arbitrary 'closure' passed to the code object."""
can_change_code = True
+ _immutable_fields_ = ['code?',
+ 'w_func_globals?',
+ 'closure?',
+ 'defs_w?[*]']
def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
- forcename=None, promote_defs=False):
+ forcename=None):
self.space = space
self.name = forcename or code.co_name
self.w_doc = None # lazily read from code.getdocstring()
self.code = code # Code instance
self.w_func_globals = w_globals # the globals dictionary
self.closure = closure # normally, list of Cell instances or None
- self.defs = Defaults(defs_w, promote=promote_defs)
- # wrapper around list of w_default's
+ self.defs_w = defs_w
self.w_func_dict = None # filled out below if needed
self.w_module = None
@@ -157,7 +138,7 @@
return self._flat_pycall(code, nargs, frame)
elif fast_natural_arity & Code.FLATPYCALL:
natural_arity = fast_natural_arity & 0xff
- if natural_arity > nargs >= natural_arity - self.defs.getlen():
+ if natural_arity > nargs >= natural_arity - len(self.defs_w):
assert isinstance(code, PyCode)
return self._flat_pycall_defaults(code, nargs, frame,
natural_arity - nargs)
@@ -190,12 +171,11 @@
w_arg = frame.peekvalue(nargs-1-i)
new_frame.fastlocals_w[i] = w_arg
- defs = self.defs
- ndefs = defs.getlen()
+ ndefs = len(self.defs_w)
start = ndefs - defs_to_load
i = nargs
for j in xrange(start, ndefs):
- new_frame.fastlocals_w[i] = defs.getitem(j)
+ new_frame.fastlocals_w[i] = self.defs_w[j]
i += 1
return new_frame.run()
@@ -311,7 +291,7 @@
w(self.code),
w_func_globals,
w_closure,
- nt(self.defs.getitems()),
+ nt(self.defs_w),
w_func_dict,
self.w_module,
]
@@ -346,11 +326,11 @@
if space.is_w(w_func_dict, space.w_None):
w_func_dict = None
self.w_func_dict = w_func_dict
- self.defs = Defaults(space.fixedview(w_defs))
+ self.defs_w = space.fixedview(w_defs)
self.w_module = w_module
def fget_func_defaults(self, space):
- values_w = self.defs.getitems()
+ values_w = self.defs_w
# the `None in values_w` check here is to ensure that interp-level
# functions with a default of NoneNotWrapped do not get their defaults
# exposed at applevel
@@ -360,14 +340,14 @@
def fset_func_defaults(self, space, w_defaults):
if space.is_w(w_defaults, space.w_None):
- self.defs = Defaults([])
+ self.defs_w = []
return
if not space.is_true(space.isinstance(w_defaults, space.w_tuple)):
raise OperationError( space.w_TypeError, space.wrap("func_defaults must be set to a tuple object or None") )
- self.defs = Defaults(space.fixedview(w_defaults))
+ self.defs_w = space.fixedview(w_defaults)
def fdel_func_defaults(self, space):
- self.defs = Defaults([])
+ self.defs_w = []
def fget_func_doc(self, space):
if self.w_doc is None:
@@ -448,6 +428,7 @@
class Method(Wrappable):
"""A method is a function bound to a specific instance or class."""
+ _immutable_fields_ = ['w_function', 'w_instance', 'w_class']
def __init__(self, space, w_function, w_instance, w_class):
self.space = space
@@ -631,8 +612,7 @@
def __init__(self, func):
assert isinstance(func, Function)
Function.__init__(self, func.space, func.code, func.w_func_globals,
- func.defs.getitems(), func.closure, func.name,
- promote_defs=True)
+ func.defs_w, func.closure, func.name)
self.w_doc = func.w_doc
self.w_func_dict = func.w_func_dict
self.w_module = func.w_module
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -594,7 +594,7 @@
space = func.space
activation = self.activation
scope_w = args.parse_obj(w_obj, func.name, self.sig,
- func.defs, self.minargs)
+ func.defs_w, self.minargs)
try:
w_result = activation._run(space, scope_w)
except DescrMismatch:
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -7,6 +7,7 @@
class GeneratorIterator(Wrappable):
"An iterator created by a generator."
+ _immutable_fields_ = ['pycode']
def __init__(self, frame):
self.space = frame.space
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -204,7 +204,7 @@
fresh_virtualizable=True)
args_matched = args.parse_into_scope(None, fresh_frame.fastlocals_w,
func.name,
- sig, func.defs)
+ sig, func.defs_w)
fresh_frame.init_cells()
return frame.run()
@@ -217,7 +217,7 @@
fresh_virtualizable=True)
args_matched = args.parse_into_scope(w_obj, fresh_frame.fastlocals_w,
func.name,
- sig, func.defs)
+ sig, func.defs_w)
fresh_frame.init_cells()
return frame.run()
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1197,6 +1197,7 @@
WHY_CONTINUE, SContinueLoop
WHY_YIELD not needed
"""
+ _immutable_ = True
def nomoreblocks(self):
raise BytecodeCorruption("misplaced bytecode - should not return")
@@ -1207,6 +1208,7 @@
class SReturnValue(SuspendedUnroller):
"""Signals a 'return' statement.
Argument is the wrapped object to return."""
+ _immutable_ = True
kind = 0x01
def __init__(self, w_returnvalue):
self.w_returnvalue = w_returnvalue
@@ -1222,6 +1224,7 @@
class SApplicationException(SuspendedUnroller):
"""Signals an application-level exception
(i.e. an OperationException)."""
+ _immutable_ = True
kind = 0x02
def __init__(self, operr):
self.operr = operr
@@ -1236,6 +1239,7 @@
class SBreakLoop(SuspendedUnroller):
"""Signals a 'break' statement."""
+ _immutable_ = True
kind = 0x04
def state_unpack_variables(self, space):
@@ -1249,6 +1253,7 @@
class SContinueLoop(SuspendedUnroller):
"""Signals a 'continue' statement.
Argument is the bytecode position of the beginning of the loop."""
+ _immutable_ = True
kind = 0x08
def __init__(self, jump_to):
self.jump_to = jump_to
@@ -1261,10 +1266,11 @@
class FrameBlock(object):
-
"""Abstract base class for frame blocks from the blockstack,
used by the SETUP_XXX and POP_BLOCK opcodes."""
+ _immutable_ = True
+
def __init__(self, frame, handlerposition):
self.handlerposition = handlerposition
self.valuestackdepth = frame.valuestackdepth
@@ -1306,6 +1312,7 @@
class LoopBlock(FrameBlock):
"""A loop block. Stores the end-of-loop pointer in case of 'break'."""
+ _immutable_ = True
_opname = 'SETUP_LOOP'
handling_mask = SBreakLoop.kind | SContinueLoop.kind
@@ -1325,6 +1332,7 @@
class ExceptBlock(FrameBlock):
"""An try:except: block. Stores the position of the exception handler."""
+ _immutable_ = True
_opname = 'SETUP_EXCEPT'
handling_mask = SApplicationException.kind
@@ -1349,6 +1357,7 @@
class FinallyBlock(FrameBlock):
"""A try:finally: block. Stores the position of the exception handler."""
+ _immutable_ = True
_opname = 'SETUP_FINALLY'
handling_mask = -1 # handles every kind of SuspendedUnroller
@@ -1376,6 +1385,8 @@
class WithBlock(FinallyBlock):
+ _immutable_ = True
+
def really_handle(self, frame, unroller):
if (frame.space.full_exceptions and
isinstance(unroller, SApplicationException)):
diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -3,7 +3,6 @@
ArgErr, ArgErrUnknownKwds, ArgErrMultipleValues, ArgErrCount, rawshape,
Signature)
from pypy.interpreter.error import OperationError
-from pypy.interpreter.function import Defaults
class TestSignature(object):
@@ -184,7 +183,7 @@
py.test.raises(ArgErr, args._match_signature, None, l, Signature(["a"], "*"))
args = Arguments(space, [])
l = [None]
- args._match_signature(None, l, Signature(["a"]), defaults=Defaults([1]))
+ args._match_signature(None, l, Signature(["a"]), defaults_w=[1])
assert l == [1]
args = Arguments(space, [])
l = [None]
@@ -232,7 +231,7 @@
py.test.raises(ArgErr, args._match_signature, firstarg, l, Signature(["a", "b", "c", "d", "e"], "*"))
l = [None, None, None, None, None]
args = Arguments(space, arglist, w_stararg=starargs)
- args._match_signature(firstarg, l, Signature(["a", "b", "c", "d", "e"]), defaults=Defaults([1]))
+ args._match_signature(firstarg, l, Signature(["a", "b", "c", "d", "e"]), defaults_w=[1])
assert l == [4, 5, 6, 7, 1]
for j in range(len(values)):
l = [None] * (j + 1)
@@ -257,24 +256,24 @@
assert len(keywords) == len(keywords_w)
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None]
- args._match_signature(None, l, Signature(["a", "b", "c"]), defaults=Defaults([4]))
+ args._match_signature(None, l, Signature(["a", "b", "c"]), defaults_w=[4])
assert l == [1, 2, 3]
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None, None]
- args._match_signature(None, l, Signature(["a", "b", "b1", "c"]), defaults=Defaults([4, 5]))
+ args._match_signature(None, l, Signature(["a", "b", "b1", "c"]), defaults_w=[4, 5])
assert l == [1, 2, 4, 3]
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None, None]
- args._match_signature(None, l, Signature(["a", "b", "c", "d"]), defaults=Defaults([4, 5]))
+ args._match_signature(None, l, Signature(["a", "b", "c", "d"]), defaults_w=[4, 5])
assert l == [1, 2, 3, 5]
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None, None]
py.test.raises(ArgErr, args._match_signature, None, l,
- Signature(["c", "b", "a", "d"]), defaults=Defaults([4, 5]))
+ Signature(["c", "b", "a", "d"]), defaults_w=[4, 5])
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None, None]
py.test.raises(ArgErr, args._match_signature, None, l,
- Signature(["a", "b", "c1", "d"]), defaults=Defaults([4, 5]))
+ Signature(["a", "b", "c1", "d"]), defaults_w=[4, 5])
args = Arguments(space, [1, 2], keywords[:], keywords_w[:], w_starstararg=w_kwds)
l = [None, None, None]
args._match_signature(None, l, Signature(["a", "b"], None, "**"))
@@ -355,10 +354,10 @@
calls = []
def _match_signature(w_firstarg, scope_w, signature,
- defaults=None, blindargs=0):
- defaults = [] if defaults is None else defaults.getitems()
+ defaults_w=None, blindargs=0):
+ defaults_w = [] if defaults_w is None else defaults_w
calls.append((w_firstarg, scope_w, signature.argnames, signature.has_vararg(),
- signature.has_kwarg(), defaults, blindargs))
+ signature.has_kwarg(), defaults_w, blindargs))
args._match_signature = _match_signature
scope_w = args.parse_obj(None, "foo", Signature(["a", "b"], None, None))
@@ -376,7 +375,7 @@
calls = []
scope_w = args.parse_obj(None, "foo", Signature(["a", "b"], "args", "kw"),
- defaults=Defaults(['x', 'y']))
+ defaults_w=['x', 'y'])
assert len(calls) == 1
assert calls[0] == (None, [None, None, None, None], ["a", "b"],
True, True,
@@ -384,7 +383,7 @@
calls = []
scope_w = args.parse_obj("obj", "foo", Signature(["a", "b"], "args", "kw"),
- defaults=Defaults(['x', 'y']), blindargs=1)
+ defaults_w=['x', 'y'], blindargs=1)
assert len(calls) == 1
assert calls[0] == ("obj", [None, None, None, None], ["a", "b"],
True, True,
@@ -413,10 +412,10 @@
calls = []
def _match_signature(w_firstarg, scope_w, signature,
- defaults=None, blindargs=0):
- defaults = [] if defaults is None else defaults.getitems()
+ defaults_w=None, blindargs=0):
+ defaults_w = [] if defaults_w is None else defaults_w
calls.append((w_firstarg, scope_w, signature.argnames, signature.has_vararg(),
- signature.has_kwarg(), defaults, blindargs))
+ signature.has_kwarg(), defaults_w, blindargs))
args._match_signature = _match_signature
scope_w = [None, None]
@@ -429,7 +428,7 @@
scope_w = [None, None, None, None]
args.parse_into_scope(None, scope_w, "foo", Signature(["a", "b"], "args", "kw"),
- defaults=Defaults(['x', 'y']))
+ defaults_w=['x', 'y'])
assert len(calls) == 1
assert calls[0] == (None, scope_w, ["a", "b"],
True, True,
@@ -439,7 +438,7 @@
scope_w = [None, None, None, None]
args.parse_into_scope("obj", scope_w, "foo", Signature(["a", "b"],
"args", "kw"),
- defaults=Defaults(['x', 'y']))
+ defaults_w=['x', 'y'])
assert len(calls) == 1
assert calls[0] == ("obj", scope_w, ["a", "b"],
True, True,
@@ -511,25 +510,25 @@
def test_missing_args(self):
# got_nargs, nkwds, expected_nargs, has_vararg, has_kwarg,
# defaults_w, missing_args
- err = ArgErrCount(1, 0, 0, False, False, Defaults([]), 0)
+ err = ArgErrCount(1, 0, 0, False, False, None, 0)
s = err.getmsg('foo')
assert s == "foo() takes no argument (1 given)"
- err = ArgErrCount(0, 0, 1, False, False, Defaults([]), 1)
+ err = ArgErrCount(0, 0, 1, False, False, [], 1)
s = err.getmsg('foo')
assert s == "foo() takes exactly 1 argument (0 given)"
- err = ArgErrCount(3, 0, 2, False, False, Defaults([]), 0)
+ err = ArgErrCount(3, 0, 2, False, False, [], 0)
s = err.getmsg('foo')
assert s == "foo() takes exactly 2 arguments (3 given)"
- err = ArgErrCount(1, 0, 2, True, False, Defaults([]), 1)
+ err = ArgErrCount(1, 0, 2, True, False, [], 1)
s = err.getmsg('foo')
assert s == "foo() takes at least 2 arguments (1 given)"
- err = ArgErrCount(3, 0, 2, True, False, Defaults(['a']), 0)
+ err = ArgErrCount(3, 0, 2, True, False, ['a'], 0)
s = err.getmsg('foo')
assert s == "foo() takes at most 2 arguments (3 given)"
- err = ArgErrCount(0, 1, 2, True, False, Defaults(['a']), 1)
+ err = ArgErrCount(0, 1, 2, True, False, ['a'], 1)
s = err.getmsg('foo')
assert s == "foo() takes at least 1 argument (1 given)"
- err = ArgErrCount(2, 1, 1, False, True, Defaults([]), 0)
+ err = ArgErrCount(2, 1, 1, False, True, [], 0)
s = err.getmsg('foo')
assert s == "foo() takes exactly 1 argument (3 given)"
@@ -603,7 +602,7 @@
args = make_arguments_for_translation(space, [1])
sig = Signature(['a', 'b', 'c'], None, None)
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
@@ -615,25 +614,25 @@
args = make_arguments_for_translation(space, [1], {'c': 3, 'b': 2})
sig = Signature(['a', 'b', 'c'], None, None)
- data = args.match_signature(sig, Defaults([]))
+ data = args.match_signature(sig, [])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
args = make_arguments_for_translation(space, [1], {'c': 5})
sig = Signature(['a', 'b', 'c'], None, None)
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
args = make_arguments_for_translation(space, [1], {'c': 5, 'd': 7})
sig = Signature(['a', 'b', 'c'], None, 'kw')
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
args = make_arguments_for_translation(space, [1,2,3,4,5], {'e': 5, 'd': 7})
sig = Signature(['a', 'b', 'c'], 'r', 'kw')
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
@@ -641,7 +640,7 @@
w_stararg=[1],
w_starstararg={'c': 5, 'd': 7})
sig = Signature(['a', 'b', 'c'], None, 'kw')
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
@@ -649,7 +648,7 @@
w_stararg=[3,4,5],
w_starstararg={'e': 5, 'd': 7})
sig = Signature(['a', 'b', 'c'], 'r', 'kw')
- data = args.match_signature(sig, Defaults([2, 3]))
+ data = args.match_signature(sig, [2, 3])
new_args = args.unmatch_signature(sig, data)
assert args.unpack() == new_args.unpack()
diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -4,7 +4,6 @@
from pypy.conftest import gettestobjspace
from pypy.interpreter import gateway, argument
from pypy.interpreter.gateway import ObjSpace, W_Root
-from pypy.interpreter.function import Defaults
import py
import sys
@@ -12,7 +11,7 @@
def __init__(self, space, name):
self.space = space
self.name = name
- self.defs = Defaults([])
+ self.defs_w = []
class TestBuiltinCode:
def test_signature(self):
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -168,6 +168,7 @@
class CompiledLoop(object):
has_been_freed = False
+ invalid = False
def __init__(self):
self.inputargs = []
@@ -944,6 +945,9 @@
if forced:
raise GuardFailed
+ def op_guard_not_invalidated(self, descr):
+ if self.loop.invalid:
+ raise GuardFailed
class OOFrame(Frame):
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -286,6 +286,10 @@
raise ValueError("CALL_ASSEMBLER not supported")
llimpl.redirect_call_assembler(self, oldlooptoken, newlooptoken)
+ def invalidate_loop(self, looptoken):
+ for loop in looptoken.compiled_loop_token.loop_and_bridges:
+ loop._obj.externalobj.invalid = True
+
# ----------
def sizeof(self, S):
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -136,6 +136,16 @@
oldlooptoken so that from now own they will call newlooptoken."""
raise NotImplementedError
+ def invalidate_loop(self, looptoken):
+ """Activate all GUARD_NOT_INVALIDATED in the loop and its attached
+ bridges. Before this call, all GUARD_NOT_INVALIDATED do nothing;
+ after this call, they all fail. Note that afterwards, if one such
+ guard fails often enough, it has a bridge attached to it; it is
+ possible then to re-call invalidate_loop() on the same looptoken,
+ which must invalidate all newer GUARD_NOT_INVALIDATED, but not the
+ old one that already has a bridge attached to it."""
+ raise NotImplementedError
+
def free_loop_and_bridges(self, compiled_loop_token):
"""This method is called to free resources (machine code,
references to resume guards, etc.) allocated by the compilation
@@ -291,6 +301,7 @@
# that belong to this loop or to a bridge attached to it.
# Filled by the frontend calling record_faildescr_index().
self.faildescr_indices = []
+ self.invalidate_positions = []
debug_start("jit-mem-looptoken-alloc")
debug_print("allocating Loop #", self.number)
debug_stop("jit-mem-looptoken-alloc")
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -1841,6 +1841,66 @@
assert self.cpu.get_latest_value_int(2) == 10
assert values == [1, 10]
+ def test_guard_not_invalidated(self):
+ cpu = self.cpu
+ i0 = BoxInt()
+ i1 = BoxInt()
+ faildescr = BasicFailDescr(1)
+ ops = [
+ ResOperation(rop.GUARD_NOT_INVALIDATED, [], None, descr=faildescr),
+ ResOperation(rop.FINISH, [i0], None, descr=BasicFailDescr(0))
+ ]
+ ops[0].setfailargs([i1])
+ looptoken = LoopToken()
+ self.cpu.compile_loop([i0, i1], ops, looptoken)
+
+ self.cpu.set_future_value_int(0, -42)
+ self.cpu.set_future_value_int(1, 9)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail.identifier == 0
+ assert self.cpu.get_latest_value_int(0) == -42
+ print 'step 1 ok'
+ print '-'*79
+
+ # mark as failing
+ self.cpu.invalidate_loop(looptoken)
+
+ self.cpu.set_future_value_int(0, -42)
+ self.cpu.set_future_value_int(1, 9)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail is faildescr
+ assert self.cpu.get_latest_value_int(0) == 9
+ print 'step 2 ok'
+ print '-'*79
+
+ # attach a bridge
+ i2 = BoxInt()
+ faildescr2 = BasicFailDescr(2)
+ ops = [
+ ResOperation(rop.GUARD_NOT_INVALIDATED, [],None, descr=faildescr2),
+ ResOperation(rop.FINISH, [i2], None, descr=BasicFailDescr(3))
+ ]
+ ops[0].setfailargs([])
+ self.cpu.compile_bridge(faildescr, [i2], ops, looptoken)
+
+ self.cpu.set_future_value_int(0, -42)
+ self.cpu.set_future_value_int(1, 9)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail.identifier == 3
+ assert self.cpu.get_latest_value_int(0) == 9
+ print 'step 3 ok'
+ print '-'*79
+
+ # mark as failing again
+ self.cpu.invalidate_loop(looptoken)
+
+ self.cpu.set_future_value_int(0, -42)
+ self.cpu.set_future_value_int(1, 9)
+ fail = self.cpu.execute_token(looptoken)
+ assert fail is faildescr2
+ print 'step 4 ok'
+ print '-'*79
+
# pure do_ / descr features
def test_do_operations(self):
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -48,11 +48,13 @@
class GuardToken(object):
- def __init__(self, faildescr, failargs, fail_locs, exc):
+ def __init__(self, faildescr, failargs, fail_locs, exc,
+ is_guard_not_invalidated):
self.faildescr = faildescr
self.failargs = failargs
self.fail_locs = fail_locs
self.exc = exc
+ self.is_guard_not_invalidated = is_guard_not_invalidated
DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed))
@@ -435,15 +437,36 @@
# tok.faildescr._x86_adr_jump_offset to contain the raw address of
# the 4-byte target field in the JMP/Jcond instruction, and patch
# the field in question to point (initially) to the recovery stub
+ clt = self.current_clt
for tok in self.pending_guard_tokens:
addr = rawstart + tok.pos_jump_offset
tok.faildescr._x86_adr_jump_offset = addr
relative_target = tok.pos_recovery_stub - (tok.pos_jump_offset + 4)
assert rx86.fits_in_32bits(relative_target)
#
- mc = codebuf.MachineCodeBlockWrapper()
- mc.writeimm32(relative_target)
- mc.copy_to_raw_memory(addr)
+ if not tok.is_guard_not_invalidated:
+ mc = codebuf.MachineCodeBlockWrapper()
+ mc.writeimm32(relative_target)
+ mc.copy_to_raw_memory(addr)
+ else:
+ # GUARD_NOT_INVALIDATED, record an entry in
+ # clt.invalidate_positions of the form:
+ # (addr-in-the-code-of-the-not-yet-written-jump-target,
+ # relative-target-to-use)
+ relpos = tok.pos_jump_offset
+ clt.invalidate_positions.append((rawstart + relpos,
+ relative_target))
+ # General idea: Although no code was generated by this
+ # guard, the code might be patched with a "JMP rel32" to
+ # the guard recovery code. This recovery code is
+ # already generated, and looks like the recovery code
+ # for any guard, even if at first it has no jump to it.
+ # So we may later write 5 bytes overriding the existing
+ # instructions; this works because a CALL instruction
+ # would also take at least 5 bytes. If it could take
+ # less, we would run into the issue that overwriting the
+ # 5 bytes here might get a few nonsense bytes at the
+ # return address of the following CALL.
def get_asmmemmgr_blocks(self, looptoken):
clt = looptoken.compiled_loop_token
@@ -1471,6 +1494,12 @@
self.mc.CMP(heap(self.cpu.pos_exception()), imm0)
self.implement_guard(guard_token, 'NZ')
+ def genop_guard_guard_not_invalidated(self, ign_1, guard_op, guard_token,
+ locs, ign_2):
+ pos = self.mc.get_relative_pos() + 1 # after potential jmp
+ guard_token.pos_jump_offset = pos
+ self.pending_guard_tokens.append(guard_token)
+
def genop_guard_guard_exception(self, ign_1, guard_op, guard_token,
locs, resloc):
loc = locs[0]
@@ -1569,7 +1598,9 @@
exc = (guard_opnum == rop.GUARD_EXCEPTION or
guard_opnum == rop.GUARD_NO_EXCEPTION or
guard_opnum == rop.GUARD_NOT_FORCED)
- return GuardToken(faildescr, failargs, fail_locs, exc)
+ is_guard_not_invalidated = guard_opnum == rop.GUARD_NOT_INVALIDATED
+ return GuardToken(faildescr, failargs, fail_locs, exc,
+ is_guard_not_invalidated)
def generate_quick_failure(self, guardtok):
"""Generate the initial code for handling a failure. We try to
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -497,6 +497,8 @@
def consider_guard_no_exception(self, op):
self.perform_guard(op, [], None)
+ consider_guard_not_invalidated = consider_guard_no_exception
+
def consider_guard_exception(self, op):
loc = self.rm.make_sure_var_in_reg(op.getarg(0))
box = TempBox()
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -153,6 +153,17 @@
def redirect_call_assembler(self, oldlooptoken, newlooptoken):
self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)
+ def invalidate_loop(self, looptoken):
+ from pypy.jit.backend.x86 import codebuf
+
+ for addr, tgt in looptoken.compiled_loop_token.invalidate_positions:
+ mc = codebuf.MachineCodeBlockWrapper()
+ mc.JMP_l(tgt)
+ assert mc.get_relative_pos() == 5 # [JMP] [tgt 4 bytes]
+ mc.copy_to_raw_memory(addr - 1)
+ # positions invalidated
+ looptoken.compiled_loop_token.invalidate_positions = []
+
class CPU386(AbstractX86CPU):
WORD = 4
NUM_REGS = 8
diff --git a/pypy/jit/backend/x86/test/test_quasiimmut.py b/pypy/jit/backend/x86/test/test_quasiimmut.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/x86/test/test_quasiimmut.py
@@ -0,0 +1,9 @@
+
+import py
+from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
+from pypy.jit.metainterp.test import test_quasiimmut
+
+class TestLoopSpec(Jit386Mixin, test_quasiimmut.QuasiImmutTests):
+ # for the individual tests see
+ # ====> ../../../metainterp/test/test_loop.py
+ pass
diff --git a/pypy/jit/codewriter/call.py b/pypy/jit/codewriter/call.py
--- a/pypy/jit/codewriter/call.py
+++ b/pypy/jit/codewriter/call.py
@@ -6,6 +6,7 @@
from pypy.jit.codewriter import support
from pypy.jit.codewriter.jitcode import JitCode
from pypy.jit.codewriter.effectinfo import VirtualizableAnalyzer
+from pypy.jit.codewriter.effectinfo import QuasiImmutAnalyzer
from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze
from pypy.jit.codewriter.effectinfo import EffectInfo, CallInfoCollection
from pypy.translator.simplify import get_funcobj, get_functype
@@ -30,6 +31,7 @@
self.raise_analyzer = RaiseAnalyzer(translator)
self.readwrite_analyzer = ReadWriteAnalyzer(translator)
self.virtualizable_analyzer = VirtualizableAnalyzer(translator)
+ self.quasiimmut_analyzer = QuasiImmutAnalyzer(translator)
#
for index, jd in enumerate(jitdrivers_sd):
jd.index = index
@@ -220,6 +222,8 @@
if extraeffect is None:
if self.virtualizable_analyzer.analyze(op):
extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+ elif self.quasiimmut_analyzer.analyze(op):
+ extraeffect = EffectInfo.EF_CAN_INVALIDATE
elif loopinvariant:
extraeffect = EffectInfo.EF_LOOPINVARIANT
elif pure:
@@ -237,6 +241,7 @@
if pure or loopinvariant:
assert effectinfo is not None
assert extraeffect != EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
+ assert extraeffect != EffectInfo.EF_CAN_INVALIDATE
#
return self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), RESULT,
effectinfo)
diff --git a/pypy/jit/codewriter/codewriter.py b/pypy/jit/codewriter/codewriter.py
--- a/pypy/jit/codewriter/codewriter.py
+++ b/pypy/jit/codewriter/codewriter.py
@@ -13,13 +13,13 @@
class CodeWriter(object):
callcontrol = None # for tests
+ debug = False
- def __init__(self, cpu=None, jitdrivers_sd=[], debug=False):
+ def __init__(self, cpu=None, jitdrivers_sd=[]):
self.cpu = cpu
self.assembler = Assembler()
self.callcontrol = CallControl(cpu, jitdrivers_sd)
self._seen_files = set()
- self.debug = debug
def transform_func_to_jitcode(self, func, values, type_system='lltype'):
"""For testing."""
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -13,7 +13,8 @@
EF_LOOPINVARIANT = 1 #special: call it only once per loop
EF_CANNOT_RAISE = 2 #a function which cannot raise
EF_CAN_RAISE = 3 #normal function (can raise)
- EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE = 4 #can raise and force virtualizables
+ EF_CAN_INVALIDATE = 4 #can force all GUARD_NOT_INVALIDATED
+ EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE = 5 #can raise and force virtualizables
# the 'oopspecindex' field is one of the following values:
OS_NONE = 0 # normal case, no oopspec
@@ -100,6 +101,9 @@
cls._cache[key] = result
return result
+ def check_can_invalidate(self):
+ return self.extraeffect >= self.EF_CAN_INVALIDATE
+
def check_forces_virtual_or_virtualizable(self):
return self.extraeffect >= self.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
@@ -175,6 +179,10 @@
return op.opname in ('jit_force_virtualizable',
'jit_force_virtual')
+class QuasiImmutAnalyzer(BoolGraphAnalyzer):
+ def analyze_simple_operation(self, op, graphinfo):
+ return op.opname == 'jit_force_quasi_immutable'
+
# ____________________________________________________________
class CallInfoCollection(object):
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
@@ -9,6 +9,8 @@
from pypy.jit.codewriter.effectinfo import EffectInfo
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
@@ -113,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
@@ -362,7 +364,7 @@
# If the resulting op1 is still a direct_call, turn it into a
# residual_call.
if isinstance(op1, SpaceOperation) and op1.opname == 'direct_call':
- op1 = self.handle_residual_call(op1 or op)
+ op1 = self.handle_residual_call(op1)
return op1
def handle_recursive_call(self, op):
@@ -563,7 +565,8 @@
arraydescr)
return []
# check for _immutable_fields_ hints
- if v_inst.concretetype.TO._immutable_field(c_fieldname.value):
+ immut = v_inst.concretetype.TO._immutable_field(c_fieldname.value)
+ if immut:
if (self.callcontrol is not None and
self.callcontrol.could_be_green_field(v_inst.concretetype.TO,
c_fieldname.value)):
@@ -576,8 +579,18 @@
descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
c_fieldname.value)
kind = getkind(RESULT)[0]
- return SpaceOperation('getfield_%s_%s%s' % (argname, kind, pure),
- [v_inst, descr], op.result)
+ op1 = SpaceOperation('getfield_%s_%s%s' % (argname, kind, pure),
+ [v_inst, descr], op.result)
+ #
+ if immut in (IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY):
+ descr1 = self.cpu.fielddescrof(
+ v_inst.concretetype.TO,
+ quasiimmut.get_mutate_field_name(c_fieldname.value))
+ op1 = [SpaceOperation('-live-', [], None),
+ SpaceOperation('record_quasiimmut_field',
+ [v_inst, descr, descr1], None),
+ op1]
+ return op1
def rewrite_op_setfield(self, op):
if self.is_typeptr_getset(op):
@@ -1370,6 +1383,15 @@
return self._handle_oopspec_call(op, args, EffectInfo.OS_MATH_SQRT,
EffectInfo.EF_PURE)
+ def rewrite_op_jit_force_quasi_immutable(self, op):
+ v_inst, c_fieldname = op.args
+ descr1 = self.cpu.fielddescrof(v_inst.concretetype.TO,
+ c_fieldname.value)
+ op0 = SpaceOperation('-live-', [], None)
+ op1 = SpaceOperation('jit_force_quasi_immutable', [v_inst, descr1],
+ None)
+ return [op0, op1]
+
# ____________________________________________________________
class NotSupported(Exception):
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
@@ -969,3 +969,48 @@
assert op1.args[3] == ListOfKind("ref", [])
assert op1.args[4] == ListOfKind('float', [v1])
assert op1.result == v2
+
+def test_quasi_immutable():
+ from pypy.rpython.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
+ accessor = FieldListAccessor()
+ accessor.initialize(None, {'inst_x': IR_QUASIIMMUTABLE})
+ v2 = varoftype(lltype.Signed)
+ STRUCT = lltype.GcStruct('struct', ('inst_x', lltype.Signed),
+ ('mutate_x', rclass.OBJECTPTR),
+ hints={'immutable_fields': accessor})
+ for v_x in [const(lltype.malloc(STRUCT)), varoftype(lltype.Ptr(STRUCT))]:
+ op = SpaceOperation('getfield', [v_x, Constant('inst_x', lltype.Void)],
+ v2)
+ tr = Transformer(FakeCPU())
+ [_, op1, op2] = tr.rewrite_operation(op)
+ assert op1.opname == 'record_quasiimmut_field'
+ assert len(op1.args) == 3
+ assert op1.args[0] == v_x
+ assert op1.args[1] == ('fielddescr', STRUCT, 'inst_x')
+ assert op1.args[2] == ('fielddescr', STRUCT, 'mutate_x')
+ assert op1.result is None
+ assert op2.opname == 'getfield_gc_i'
+ assert len(op2.args) == 2
+ assert op2.args[0] == v_x
+ assert op2.args[1] == ('fielddescr', STRUCT, 'inst_x')
+ assert op2.result is op.result
+
+def test_quasi_immutable_setfield():
+ from pypy.rpython.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
+ accessor = FieldListAccessor()
+ accessor.initialize(None, {'inst_x': IR_QUASIIMMUTABLE})
+ v1 = varoftype(lltype.Signed)
+ STRUCT = lltype.GcStruct('struct', ('inst_x', lltype.Signed),
+ ('mutate_x', rclass.OBJECTPTR),
+ hints={'immutable_fields': accessor})
+ for v_x in [const(lltype.malloc(STRUCT)), varoftype(lltype.Ptr(STRUCT))]:
+ op = SpaceOperation('jit_force_quasi_immutable',
+ [v_x, Constant('mutate_x', lltype.Void)],
+ varoftype(lltype.Void))
+ tr = Transformer(FakeCPU(), FakeRegularCallControl())
+ tr.graph = 'currentgraph'
+ op0, op1 = tr.rewrite_operation(op)
+ assert op0.opname == '-live-'
+ assert op1.opname == 'jit_force_quasi_immutable'
+ assert op1.args[0] == v_x
+ assert op1.args[1] == ('fielddescr', STRUCT, 'mutate_x')
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -1174,6 +1174,15 @@
def bhimpl_setfield_raw_f(cpu, struct, fielddescr, newvalue):
cpu.bh_setfield_raw_f(struct, fielddescr, newvalue)
+ @arguments("r", "d", "d")
+ def bhimpl_record_quasiimmut_field(struct, fielddescr, mutatefielddescr):
+ pass
+
+ @arguments("cpu", "r", "d")
+ def bhimpl_jit_force_quasi_immutable(cpu, struct, mutatefielddescr):
+ from pypy.jit.metainterp import quasiimmut
+ quasiimmut.do_force_quasi_immutable(cpu, struct, mutatefielddescr)
+
@arguments("cpu", "d", returns="r")
def bhimpl_new(cpu, descr):
return cpu.bh_new(descr)
@@ -1299,6 +1308,8 @@
# We get here because it used to overflow, but now it no longer
# does.
pass
+ elif opnum == rop.GUARD_NOT_INVALIDATED:
+ pass
else:
from pypy.jit.metainterp.resoperation import opname
raise NotImplementedError(opname[opnum])
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -76,6 +76,11 @@
op.setdescr(None) # clear reference, mostly for tests
if not we_are_translated():
op._jumptarget_number = descr.number
+ # record this looptoken on the QuasiImmut used in the code
+ if loop.quasi_immutable_deps is not None:
+ for qmut in loop.quasi_immutable_deps:
+ qmut.register_loop_token(wref)
+ # XXX maybe we should clear the dictionary here
# mostly for tests: make sure we don't keep a reference to the LoopToken
loop.token = None
if not we_are_translated():
@@ -396,6 +401,12 @@
self.copy_all_attributes_into(res)
return res
+class ResumeGuardNotInvalidated(ResumeGuardDescr):
+ def _clone_if_mutable(self):
+ res = ResumeGuardNotInvalidated()
+ self.copy_all_attributes_into(res)
+ return res
+
class ResumeAtPositionDescr(ResumeGuardDescr):
def _clone_if_mutable(self):
res = ResumeAtPositionDescr()
diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -322,6 +322,7 @@
rop.DEBUG_MERGE_POINT,
rop.JIT_DEBUG,
rop.SETARRAYITEM_RAW,
+ rop.QUASIIMMUT_FIELD,
): # list of opcodes never executed by pyjitpl
continue
raise AssertionError("missing %r" % (key,))
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -791,6 +791,7 @@
operations = None
token = None
call_pure_results = None
+ quasi_immutable_deps = None
def __init__(self, name):
self.name = name
diff --git a/pypy/jit/metainterp/jitprof.py b/pypy/jit/metainterp/jitprof.py
--- a/pypy/jit/metainterp/jitprof.py
+++ b/pypy/jit/metainterp/jitprof.py
@@ -22,6 +22,7 @@
ABORT_BRIDGE
ABORT_ESCAPE
ABORT_BAD_LOOP
+ABORT_FORCE_QUASIIMMUT
NVIRTUALS
NVHOLES
NVREUSED
@@ -179,6 +180,8 @@
self._print_intline("abort: compiling", cnt[ABORT_BRIDGE])
self._print_intline("abort: vable escape", cnt[ABORT_ESCAPE])
self._print_intline("abort: bad loop", cnt[ABORT_BAD_LOOP])
+ self._print_intline("abort: force quasi-immut",
+ cnt[ABORT_FORCE_QUASIIMMUT])
self._print_intline("nvirtuals", cnt[NVIRTUALS])
self._print_intline("nvholes", cnt[NVHOLES])
self._print_intline("nvreused", cnt[NVREUSED])
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -41,7 +41,8 @@
# during preamble but to keep it during the loop
optimizations.append(o)
- if 'rewrite' not in enable_opts or 'virtualize' not in enable_opts:
+ if ('rewrite' not in enable_opts or 'virtualize' not in enable_opts
+ or 'heap' not in enable_opts):
optimizations.append(OptSimplify())
if inline_short_preamble:
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
@@ -119,6 +119,8 @@
self._lazy_setfields = []
# cached array items: {descr: CachedArrayItems}
self.cached_arrayitems = {}
+ self._remove_guard_not_invalidated = False
+ self._seen_guard_not_invalidated = False
def reconstruct_for_next_iteration(self, optimizer, valuemap):
new = OptHeap()
@@ -238,6 +240,8 @@
effectinfo = None
else:
effectinfo = op.getdescr().get_extra_info()
+ if effectinfo is None or effectinfo.check_can_invalidate():
+ self._seen_guard_not_invalidated = False
if effectinfo is not None:
# XXX we can get the wrong complexity here, if the lists
# XXX stored on effectinfo are large
@@ -378,6 +382,46 @@
self.cache_arrayitem_value(op.getdescr(), value, indexvalue, fieldvalue,
write=True)
+ def optimize_QUASIIMMUT_FIELD(self, op):
+ # Pattern: QUASIIMMUT_FIELD(s, descr=QuasiImmutDescr)
+ # x = GETFIELD_GC(s, descr='inst_x')
+ # If 's' is a constant (after optimizations), then we make 's.inst_x'
+ # a constant too, and we rely on the rest of the optimizations to
+ # constant-fold the following getfield_gc.
+ structvalue = self.getvalue(op.getarg(0))
+ if not structvalue.is_constant():
+ self._remove_guard_not_invalidated = True
+ return # not a constant at all; ignore QUASIIMMUT_FIELD
+ #
+ from pypy.jit.metainterp.quasiimmut import QuasiImmutDescr
+ qmutdescr = op.getdescr()
+ assert isinstance(qmutdescr, QuasiImmutDescr)
+ # check that the value is still correct; it could have changed
+ # already between the tracing and now. In this case, we are
+ # simply ignoring the QUASIIMMUT_FIELD hint and compiling it
+ # as a regular getfield.
+ if not qmutdescr.is_still_valid():
+ self._remove_guard_not_invalidated = True
+ return
+ # record as an out-of-line guard
+ if self.optimizer.quasi_immutable_deps is None:
+ self.optimizer.quasi_immutable_deps = {}
+ self.optimizer.quasi_immutable_deps[qmutdescr.qmut] = None
+ # perform the replacement in the list of operations
+ fieldvalue = self.getvalue(qmutdescr.constantfieldbox)
+ cf = self.field_cache(qmutdescr.fielddescr)
+ cf.force_lazy_setfield(self)
+ cf.remember_field_value(structvalue, fieldvalue)
+ self._remove_guard_not_invalidated = False
+
+ def optimize_GUARD_NOT_INVALIDATED(self, op):
+ if self._remove_guard_not_invalidated:
+ return
+ if self._seen_guard_not_invalidated:
+ return
+ self._seen_guard_not_invalidated = True
+ self.emit_operation(op)
+
def propagate_forward(self, op):
opnum = op.getopnum()
for value, func in optimize_ops:
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
@@ -257,6 +257,7 @@
self.pendingfields = []
self.posponedop = None
self.exception_might_have_happened = False
+ self.quasi_immutable_deps = None
self.newoperations = []
if loop is not None:
self.call_pure_results = loop.call_pure_results
@@ -309,6 +310,7 @@
new.pure_operations = self.pure_operations
new.producer = self.producer
assert self.posponedop is None
+ new.quasi_immutable_deps = self.quasi_immutable_deps
return new
@@ -410,6 +412,7 @@
self.first_optimization.propagate_forward(op)
self.i += 1
self.loop.operations = self.newoperations
+ self.loop.quasi_immutable_deps = self.quasi_immutable_deps
# accumulate counters
self.resumedata_memo.update_counters(self.metainterp_sd.profiler)
diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -20,6 +20,11 @@
op = ResOperation(rop.SAME_AS, [op.getarg(0)], op.result)
self.emit_operation(op)
+ def optimize_QUASIIMMUT_FIELD(self, op):
+ # xxx ideally we could also kill the following GUARD_NOT_INVALIDATED
+ # but it's a bit hard to implement robustly if heap.py is also run
+ pass
+
def propagate_forward(self, op):
opnum = op.getopnum()
for value, func in optimize_ops:
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -267,6 +267,8 @@
virtual_state = modifier.get_virtual_state(jump_args)
loop.preamble.operations = self.optimizer.newoperations
+ loop.preamble.quasi_immutable_deps = (
+ self.optimizer.quasi_immutable_deps)
self.optimizer = self.optimizer.reconstruct_for_next_iteration()
inputargs = self.inline(self.cloned_operations,
loop.inputargs, jump_args)
@@ -276,6 +278,7 @@
loop.preamble.operations.append(jmp)
loop.operations = self.optimizer.newoperations
+ loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps
start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
assert isinstance(start_resumedescr, ResumeGuardDescr)
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
@@ -15,7 +15,7 @@
from pypy.jit.metainterp.jitprof import EmptyProfiler
from pypy.jit.metainterp.jitprof import GUARDS, RECORDED_OPS, ABORT_ESCAPE
from pypy.jit.metainterp.jitprof import ABORT_TOO_LONG, ABORT_BRIDGE, \
- ABORT_BAD_LOOP
+ ABORT_BAD_LOOP, ABORT_FORCE_QUASIIMMUT
from pypy.jit.metainterp.jitexc import JitException, get_llexception
from pypy.rlib.rarithmetic import intmask
from pypy.rlib.objectmodel import specialize
@@ -555,6 +555,35 @@
opimpl_setfield_raw_r = _opimpl_setfield_raw_any
opimpl_setfield_raw_f = _opimpl_setfield_raw_any
+ @arguments("box", "descr", "descr", "orgpc")
+ def opimpl_record_quasiimmut_field(self, box, fielddescr,
+ mutatefielddescr, orgpc):
+ from pypy.jit.metainterp.quasiimmut import QuasiImmutDescr
+ cpu = self.metainterp.cpu
+ descr = QuasiImmutDescr(cpu, box, fielddescr, mutatefielddescr)
+ self.metainterp.history.record(rop.QUASIIMMUT_FIELD, [box],
+ None, descr=descr)
+ self.generate_guard(rop.GUARD_NOT_INVALIDATED, resumepc=orgpc)
+
+ @arguments("box", "descr", "orgpc")
+ def opimpl_jit_force_quasi_immutable(self, box, mutatefielddescr, orgpc):
+ # 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():
+ from pypy.jit.metainterp.quasiimmut import do_force_quasi_immutable
+ do_force_quasi_immutable(self.metainterp.cpu, box.getref_base(),
+ mutatefielddescr)
+ raise SwitchToBlackhole(ABORT_FORCE_QUASIIMMUT)
+ self.generate_guard(rop.GUARD_ISNULL, mutatebox, resumepc=orgpc)
+
def _nonstandard_virtualizable(self, pc, box):
# returns True if 'box' is actually not the "standard" virtualizable
# that is stored in metainterp.virtualizable_boxes[-1]
@@ -1080,6 +1109,8 @@
if opnum == rop.GUARD_NOT_FORCED:
resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd,
metainterp.jitdriver_sd)
+ elif opnum == rop.GUARD_NOT_INVALIDATED:
+ resumedescr = compile.ResumeGuardNotInvalidated()
else:
resumedescr = compile.ResumeGuardDescr()
guard_op = metainterp.history.record(opnum, moreargs, None,
@@ -1852,6 +1883,9 @@
self.handle_possible_exception()
except ChangeFrame:
pass
+ elif opnum == rop.GUARD_NOT_INVALIDATED:
+ pass # XXX we want to do something special in resume descr,
+ # but not now
elif opnum == rop.GUARD_NO_OVERFLOW: # an overflow now detected
self.execute_raised(OverflowError(), constant=True)
try:
diff --git a/pypy/jit/metainterp/quasiimmut.py b/pypy/jit/metainterp/quasiimmut.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/metainterp/quasiimmut.py
@@ -0,0 +1,121 @@
+import weakref
+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 get_mutate_field_name(fieldname):
+ if fieldname.startswith('inst_'): # lltype
+ return 'mutate_' + fieldname[5:]
+ elif fieldname.startswith('o'): # ootype
+ return 'mutate_' + fieldname[1:]
+ else:
+ raise AssertionError(fieldname)
+
+def get_current_qmut_instance(cpu, gcref, mutatefielddescr):
+ """Returns the current QuasiImmut instance in the field,
+ possibly creating one.
+ """
+ qmut_gcref = cpu.bh_getfield_gc_r(gcref, mutatefielddescr)
+ if qmut_gcref:
+ qmut = QuasiImmut.show(cpu, qmut_gcref)
+ else:
+ qmut = QuasiImmut(cpu)
+ cpu.bh_setfield_gc_r(gcref, mutatefielddescr, qmut.hide())
+ return qmut
+
+def make_invalidation_function(STRUCT, mutatefieldname):
+ #
+ def _invalidate_now(p):
+ qmut_ptr = getattr(p, mutatefieldname)
+ setattr(p, mutatefieldname, lltype.nullptr(rclass.OBJECT))
+ qmut = cast_base_ptr_to_instance(QuasiImmut, qmut_ptr)
+ qmut.invalidate()
+ _invalidate_now._dont_inline_ = True
+ #
+ def invalidation(p):
+ if getattr(p, mutatefieldname):
+ _invalidate_now(p)
+ #
+ return invalidation
+
+def do_force_quasi_immutable(cpu, p, mutatefielddescr):
+ qmut_ref = cpu.bh_getfield_gc_r(p, mutatefielddescr)
+ if qmut_ref:
+ cpu.bh_setfield_gc_r(p, mutatefielddescr, cpu.ts.NULLREF)
+ qmut_ptr = lltype.cast_opaque_ptr(rclass.OBJECTPTR, qmut_ref)
+ qmut = cast_base_ptr_to_instance(QuasiImmut, qmut_ptr)
+ qmut.invalidate()
+
+
+class QuasiImmut(object):
+ llopaque = True
+
+ def __init__(self, cpu):
+ self.cpu = cpu
+ # list of weakrefs to the LoopTokens that must be invalidated if
+ # this value ever changes
+ self.looptokens_wrefs = []
+ self.compress_limit = 30
+
+ def hide(self):
+ qmut_ptr = self.cpu.ts.cast_instance_to_base_ref(self)
+ return self.cpu.ts.cast_to_ref(qmut_ptr)
+
+ @staticmethod
+ def show(cpu, qmut_gcref):
+ qmut_ptr = cpu.ts.cast_to_baseclass(qmut_gcref)
+ return cast_base_ptr_to_instance(QuasiImmut, qmut_ptr)
+
+ def register_loop_token(self, wref_looptoken):
+ if len(self.looptokens_wrefs) > self.compress_limit:
+ self.compress_looptokens_list()
+ self.looptokens_wrefs.append(wref_looptoken)
+
+ def compress_looptokens_list(self):
+ self.looptokens_wrefs = [wref for wref in self.looptokens_wrefs
+ if wref() is not None]
+ self.compress_limit = (len(self.looptokens_wrefs) + 15) * 2
+
+ def invalidate(self):
+ # When this is called, all the loops that we record become
+ # invalid: all GUARD_NOT_INVALIDATED in these loops (and
+ # in attached bridges) must now fail.
+ wrefs = self.looptokens_wrefs
+ self.looptokens_wrefs = []
+ for wref in wrefs:
+ looptoken = wref()
+ if looptoken is not None:
+ self.cpu.invalidate_loop(looptoken)
+
+
+class QuasiImmutDescr(AbstractDescr):
+ structbox = None
+
+ def __init__(self, cpu, structbox, fielddescr, mutatefielddescr):
+ self.cpu = cpu
+ self.structbox = structbox
+ self.fielddescr = fielddescr
+ self.mutatefielddescr = mutatefielddescr
+ gcref = structbox.getref_base()
+ self.qmut = get_current_qmut_instance(cpu, gcref, mutatefielddescr)
+ self.constantfieldbox = self.get_current_constant_fieldvalue()
+
+ def get_current_constant_fieldvalue(self):
+ from pypy.jit.metainterp import executor
+ from pypy.jit.metainterp.resoperation import rop
+ fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC,
+ self.fielddescr, self.structbox)
+ return fieldbox.constbox()
+
+ def is_still_valid(self):
+ assert self.structbox is not None
+ cpu = self.cpu
+ gcref = self.structbox.getref_base()
+ qmut = get_current_qmut_instance(cpu, gcref, self.mutatefielddescr)
+ if qmut is not self.qmut:
+ return False
+ else:
+ currentbox = self.get_current_constant_fieldvalue()
+ assert self.constantfieldbox.same_constant(currentbox)
+ return True
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -380,6 +380,7 @@
'GUARD_NO_OVERFLOW/0d',
'GUARD_OVERFLOW/0d',
'GUARD_NOT_FORCED/0d',
+ 'GUARD_NOT_INVALIDATED/0d',
'_GUARD_LAST', # ----- end of guard operations -----
'_NOSIDEEFFECT_FIRST', # ----- start of no_side_effect operations -----
@@ -476,6 +477,7 @@
'VIRTUAL_REF_FINISH/2', # removed before it's passed to the backend
'COPYSTRCONTENT/5', # src, dst, srcstart, dststart, length
'COPYUNICODECONTENT/5',
+ 'QUASIIMMUT_FIELD/1d', # [objptr], descr=SlowMutateDescr
'_CANRAISE_FIRST', # ----- start of can_raise operations -----
'_CALL_FIRST',
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -8,12 +8,12 @@
from pypy.jit.metainterp import pyjitpl, history
from pypy.jit.metainterp.warmstate import set_future_value
from pypy.jit.codewriter.policy import JitPolicy
-from pypy.jit.codewriter import longlong
-from pypy.rlib.rfloat import isinf, isnan
+from pypy.jit.codewriter import codewriter, longlong
+from pypy.rlib.rfloat import isnan
def _get_jitcodes(testself, CPUClass, func, values, type_system,
supports_longlong=False, **kwds):
- from pypy.jit.codewriter import support, codewriter
+ from pypy.jit.codewriter import support
class FakeJitCell:
__compiled_merge_points = []
@@ -50,6 +50,7 @@
stats = history.Stats()
cpu = CPUClass(rtyper, stats, None, False)
cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
+ cw.debug = True
testself.cw = cw
policy = JitPolicy()
policy.set_supports_floats(True)
@@ -173,7 +174,12 @@
kwds['type_system'] = self.type_system
if "backendopt" not in kwds:
kwds["backendopt"] = False
- return ll_meta_interp(*args, **kwds)
+ old = codewriter.CodeWriter.debug
+ try:
+ codewriter.CodeWriter.debug = True
+ return ll_meta_interp(*args, **kwds)
+ finally:
+ codewriter.CodeWriter.debug = old
def interp_operations(self, f, args, **kwds):
# get the JitCodes for the function f
diff --git a/pypy/jit/metainterp/test/test_jitprof.py b/pypy/jit/metainterp/test/test_jitprof.py
--- a/pypy/jit/metainterp/test/test_jitprof.py
+++ b/pypy/jit/metainterp/test/test_jitprof.py
@@ -65,7 +65,7 @@
]
assert profiler.events == expected
assert profiler.times == [3, 2, 1, 1]
- assert profiler.counters == [1, 2, 1, 1, 3, 3, 1, 13, 2, 0, 0, 0,
+ assert profiler.counters == [1, 2, 1, 1, 3, 3, 1, 13, 2, 0, 0, 0, 0,
0, 0, 0, 0, 0]
def test_simple_loop_with_call(self):
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -5718,34 +5718,121 @@
# not obvious, because of the exception UnicodeDecodeError that
# can be raised by ll_str2unicode()
-
-
-
-##class TestOOtype(OptimizeOptTest, OOtypeMixin):
-
-## def test_instanceof(self):
-## ops = """
-## [i0]
-## p0 = new_with_vtable(ConstClass(node_vtable))
-## i1 = instanceof(p0, descr=nodesize)
-## jump(i1)
-## """
-## expected = """
-## [i0]
-## jump(1)
-## """
-## self.optimize_loop(ops, expected)
-
-## def test_instanceof_guard_class(self):
-## ops = """
-## [i0, p0]
-## guard_class(p0, ConstClass(node_vtable)) []
-## i1 = instanceof(p0, descr=nodesize)
-## jump(i1, p0)
-## """
-## expected = """
-## [i0, p0]
-## guard_class(p0, ConstClass(node_vtable)) []
-## jump(1, p0)
-## """
-## self.optimize_loop(ops, expected)
+ def test_quasi_immut(self):
+ ops = """
+ [p0, p1, i0]
+ quasiimmut_field(p0, descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i1 = getfield_gc(p0, descr=quasifielddescr)
+ escape(i1)
+ jump(p1, p0, i1)
+ """
+ expected = """
+ [p0, p1, i0]
+ i1 = getfield_gc(p0, descr=quasifielddescr)
+ escape(i1)
+ jump(p1, p0, i1)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_quasi_immut_2(self):
+ ops = """
+ []
+ quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i1 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+ escape(i1)
+ jump()
+ """
+ expected = """
+ []
+ guard_not_invalidated() []
+ escape(-4247)
+ jump()
+ """
+ self.optimize_loop(ops, expected, expected)
+
+ def test_remove_extra_guards_not_invalidated(self):
+ ops = """
+ [i0]
+ guard_not_invalidated() []
+ guard_not_invalidated() []
+ i1 = int_add(i0, 1)
+ guard_not_invalidated() []
+ guard_not_invalidated() []
+ jump(i1)
+ """
+ expected = """
+ [i0]
+ guard_not_invalidated() []
+ i1 = int_add(i0, 1)
+ jump(i1)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_call_may_force_invalidated_guards(self):
+ ops = """
+ [i0]
+ guard_not_invalidated() []
+ call_may_force(i0, descr=mayforcevirtdescr)
+ guard_not_invalidated() []
+ jump(i0)
+ """
+ expected = """
+ [i0]
+ guard_not_invalidated() []
+ call_may_force(i0, descr=mayforcevirtdescr)
+ guard_not_invalidated() []
+ jump(i0)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_call_may_force_invalidated_guards_reload(self):
+ ops = """
+ [i0a, i0b]
+ quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i1 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+ call_may_force(i0b, descr=mayforcevirtdescr)
+ quasiimmut_field(ConstPtr(myptr), descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i2 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
+ i3 = escape(i1)
+ i4 = escape(i2)
+ jump(i3, i4)
+ """
+ expected = """
+ [i0a, i0b]
+ guard_not_invalidated() []
+ call_may_force(i0b, descr=mayforcevirtdescr)
+ guard_not_invalidated() []
+ i3 = escape(-4247)
+ i4 = escape(-4247)
+ jump(i3, i4)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_call_may_force_invalidated_guards_virtual(self):
+ ops = """
+ [i0a, i0b]
+ p = new(descr=quasisize)
+ setfield_gc(p, 421, descr=quasifielddescr)
+ quasiimmut_field(p, descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i1 = getfield_gc(p, descr=quasifielddescr)
+ call_may_force(i0b, descr=mayforcevirtdescr)
+ quasiimmut_field(p, descr=quasiimmutdescr)
+ guard_not_invalidated() []
+ i2 = getfield_gc(p, descr=quasifielddescr)
+ i3 = escape(i1)
+ i4 = escape(i2)
+ jump(i3, i4)
+ """
+ expected = """
+ [i0a, i0b]
+ call_may_force(i0b, descr=mayforcevirtdescr)
+ i3 = escape(421)
+ i4 = escape(421)
+ jump(i3, i4)
+ """
+ self.optimize_loop(ops, expected)
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,6 +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_QUASIIMMUTABLE
from pypy.jit.backend.llgraph import runner
from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr,
@@ -12,6 +13,7 @@
from pypy.jit.codewriter.effectinfo import EffectInfo
from pypy.jit.codewriter.heaptracker import register_known_gctype, adr2int
from pypy.jit.tool.oparser import parse
+from pypy.jit.metainterp.quasiimmut import QuasiImmutDescr
def test_sort_descrs():
class PseudoDescr(AbstractDescr):
@@ -62,6 +64,20 @@
nextdescr = cpu.fielddescrof(NODE, 'next')
otherdescr = cpu.fielddescrof(NODE2, 'other')
+ accessor = FieldListAccessor()
+ accessor.initialize(None, {'inst_field': IR_QUASIIMMUTABLE})
+ QUASI = lltype.GcStruct('QUASIIMMUT', ('inst_field', lltype.Signed),
+ ('mutate_field', rclass.OBJECTPTR),
+ hints={'immutable_fields': accessor})
+ quasisize = cpu.sizeof(QUASI)
+ quasi = lltype.malloc(QUASI, immortal=True)
+ quasi.inst_field = -4247
+ quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field')
+ quasibox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, quasi))
+ quasiimmutdescr = QuasiImmutDescr(cpu, quasibox,
+ quasifielddescr,
+ cpu.fielddescrof(QUASI, 'mutate_field'))
+
NODEOBJ = lltype.GcStruct('NODEOBJ', ('parent', OBJECT),
('ref', lltype.Ptr(OBJECT)))
nodeobj = lltype.malloc(NODEOBJ)
diff --git a/pypy/jit/metainterp/test/test_quasiimmut.py b/pypy/jit/metainterp/test/test_quasiimmut.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/metainterp/test/test_quasiimmut.py
@@ -0,0 +1,462 @@
+
+import py
+
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass
+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
+from pypy.jit.metainterp.test.support import LLJitMixin
+from pypy.jit.codewriter.policy import StopAtXPolicy
+from pypy.rlib.jit import JitDriver, dont_look_inside
+
+
+def test_get_current_qmut_instance():
+ accessor = FieldListAccessor()
+ accessor.initialize(None, {'inst_x': IR_QUASIIMMUTABLE})
+ STRUCT = lltype.GcStruct('Foo', ('inst_x', lltype.Signed),
+ ('mutate_x', rclass.OBJECTPTR),
+ hints={'immutable_fields': accessor})
+ foo = lltype.malloc(STRUCT, zero=True)
+ foo.inst_x = 42
+ assert not foo.mutate_x
+
+ class FakeCPU:
+ ts = typesystem.llhelper
+
+ def bh_getfield_gc_r(self, gcref, fielddescr):
+ assert fielddescr == mutatefielddescr
+ foo = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref)
+ result = foo.mutate_x
+ return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+
+ def bh_setfield_gc_r(self, gcref, fielddescr, newvalue_gcref):
+ assert fielddescr == mutatefielddescr
+ foo = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref)
+ newvalue = lltype.cast_opaque_ptr(rclass.OBJECTPTR, newvalue_gcref)
+ foo.mutate_x = newvalue
+
+ cpu = FakeCPU()
+ mutatefielddescr = ('fielddescr', STRUCT, 'mutate_x')
+
+ foo_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, foo)
+ qmut1 = get_current_qmut_instance(cpu, foo_gcref, mutatefielddescr)
+ assert isinstance(qmut1, QuasiImmut)
+ qmut2 = get_current_qmut_instance(cpu, foo_gcref, mutatefielddescr)
+ assert qmut1 is qmut2
+
+
+class QuasiImmutTests(object):
+
+ def test_simple_1(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ def f(a, x):
+ foo = Foo(a)
+ 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.a
+ x -= 1
+ return total
+ #
+ res = self.meta_interp(f, [100, 7])
+ assert res == 700
+ self.check_loops(guard_not_invalidated=2, getfield_gc=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_nonopt_1(self):
+ myjitdriver = JitDriver(greens=[], reds=['x', 'total', 'lst'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ def setup(x):
+ return [Foo(100 + i) for i in range(x)]
+ def f(a, x):
+ lst = setup(x)
+ total = 0
+ while x > 0:
+ myjitdriver.jit_merge_point(lst=lst, x=x, total=total)
+ # read a quasi-immutable field out of a variable
+ x -= 1
+ total += lst[x].a
+ return total
+ #
+ assert f(100, 7) == 721
+ res = self.meta_interp(f, [100, 7])
+ assert res == 721
+ self.check_loops(guard_not_invalidated=0, getfield_gc=1)
+ #
+ from pypy.jit.metainterp.warmspot import get_stats
+ loops = get_stats().loops
+ for loop in loops:
+ assert loop.quasi_immutable_deps is None
+
+ def test_opt_via_virtual_1(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ class A:
+ pass
+ def f(a, x):
+ foo = Foo(a)
+ total = 0
+ while x > 0:
+ myjitdriver.jit_merge_point(foo=foo, x=x, total=total)
+ # make it a Constant after optimization only
+ a = A()
+ a.foo = foo
+ foo = a.foo
+ # read a quasi-immutable field out of it
+ total += foo.a
+ x -= 1
+ return total
+ #
+ res = self.meta_interp(f, [100, 7])
+ assert res == 700
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0,
+ everywhere=True)
+
+ def test_change_during_tracing_1(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ @dont_look_inside
+ def residual_call(foo):
+ foo.a += 1
+ def f(a, x):
+ foo = Foo(a)
+ 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.a
+ residual_call(foo)
+ x -= 1
+ return total
+ #
+ assert f(100, 7) == 721
+ res = self.meta_interp(f, [100, 7])
+ assert res == 721
+ self.check_loops(guard_not_invalidated=0, getfield_gc=1)
+
+ def test_change_during_tracing_2(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ @dont_look_inside
+ def residual_call(foo, difference):
+ foo.a += difference
+ def f(a, x):
+ foo = Foo(a)
+ 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.a
+ residual_call(foo, +1)
+ residual_call(foo, -1)
+ x -= 1
+ return total
+ #
+ assert f(100, 7) == 700
+ res = self.meta_interp(f, [100, 7])
+ assert res == 700
+ self.check_loops(guard_not_invalidated=0, getfield_gc=1)
+
+ def test_change_invalidate_reentering(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ def f(foo, x):
+ 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.a
+ x -= 1
+ return total
+ def g(a, x):
+ foo = Foo(a)
+ res1 = f(foo, x)
+ foo.a += 1 # invalidation, while the jit is not running
+ res2 = f(foo, x) # should still mark the loop as invalid
+ return res1 * 1000 + res2
+ #
+ assert g(100, 7) == 700707
+ res = self.meta_interp(g, [100, 7])
+ assert res == 700707
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0)
+
+ def test_invalidate_while_running(self):
+ jitdriver = JitDriver(greens=['foo'], reds=['i', 'total'])
+
+ class Foo(object):
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+
+ def external(foo, v):
+ if v:
+ foo.a = 2
+
+ def f(foo):
+ i = 0
+ total = 0
+ while i < 10:
+ jitdriver.jit_merge_point(i=i, foo=foo, total=total)
+ external(foo, i > 7)
+ i += 1
+ total += foo.a
+ return total
+
+ def g():
+ return f(Foo(1))
+
+ assert self.meta_interp(g, [], policy=StopAtXPolicy(external)) == g()
+
+ def test_invalidate_by_setfield(self):
+ jitdriver = JitDriver(greens=['bc', 'foo'], reds=['i', 'total'])
+
+ class Foo(object):
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+
+ def f(foo, bc):
+ i = 0
+ total = 0
+ while i < 10:
+ jitdriver.jit_merge_point(bc=bc, i=i, foo=foo, total=total)
+ if bc == 0:
+ f(foo, 1)
+ if bc == 1:
+ foo.a = int(i > 5)
+ i += 1
+ total += foo.a
+ return total
+
+ def g():
+ return f(Foo(1), 0)
+
+ assert self.meta_interp(g, []) == g()
+
+ def test_invalidate_bridge(self):
+ jitdriver = JitDriver(greens=['foo'], reds=['i', 'total'])
+
+ class Foo(object):
+ _immutable_fields_ = ['a?']
+
+ def f(foo):
+ i = 0
+ total = 0
+ while i < 10:
+ jitdriver.jit_merge_point(i=i, total=total, foo=foo)
+ if i > 5:
+ total += foo.a
+ else:
+ total += 2*foo.a
+ i += 1
+ return total
+
+ def main():
+ foo = Foo()
+ foo.a = 1
+ total = f(foo)
+ foo.a = 2
+ total += f(foo)
+ foo.a = 1
+ total += f(foo)
+ return total
+
+ res = self.meta_interp(main, [])
+ self.check_loop_count(7)
+ assert res == main()
+
+ def test_change_during_running(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ @dont_look_inside
+ def residual_call(foo, x):
+ if x == 5:
+ foo.a += 1
+ def f(a, x):
+ foo = Foo(a)
+ 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.a
+ residual_call(foo, x)
+ total += foo.a
+ 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,
+ 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(guard_not_invalidated=2, 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_length_1(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['lst?[*]']
+ def __init__(self, lst):
+ self.lst = lst
+ class A:
+ pass
+ 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)
+ # make it a Constant after optimization only
+ a = A()
+ a.foo = foo
+ foo = a.foo
+ # read a quasi-immutable field out of it
+ total += foo.lst[1]
+ # also read the length
+ total += len(foo.lst)
+ x -= 1
+ return total
+ #
+ res = self.meta_interp(f, [100, 7])
+ assert res == 714
+ self.check_loops(guard_not_invalidated=2, getfield_gc=0,
+ getarrayitem_gc=0, getarrayitem_gc_pure=0,
+ arraylen_gc=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_pass_around(self):
+ py.test.skip("think about a way to fix it")
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['lst?[*]']
+ def __init__(self, lst):
+ self.lst = lst
+ def g(lst):
+ # here, 'lst' is statically annotated as a "modified" list,
+ # so the following doesn't generate a getarrayitem_gc_pure...
+ return lst[1]
+ def f(a, x):
+ lst1 = [0, 0]
+ g(lst1)
+ 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 += g(foo.lst)
+ x -= 1
+ return total
+ #
+ res = self.meta_interp(f, [100, 7])
+ assert res == 700
+ self.check_loops(guard_not_invalidated=2, 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,6 +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_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
@@ -45,7 +46,7 @@
('inst_node', lltype.Ptr(LLtypeMixin.NODE)),
hints = {'virtualizable2_accessor': FieldListAccessor()})
XY._hints['virtualizable2_accessor'].initialize(
- XY, {'inst_x' : "", 'inst_node' : ""})
+ XY, {'inst_x' : IR_IMMUTABLE, 'inst_node' : IR_IMMUTABLE})
xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable, 'XY')
@@ -210,7 +211,8 @@
('inst_l2', lltype.Ptr(lltype.GcArray(lltype.Signed))),
hints = {'virtualizable2_accessor': FieldListAccessor()})
XY2._hints['virtualizable2_accessor'].initialize(
- XY2, {'inst_x' : "", 'inst_l1' : "[*]", 'inst_l2' : "[*]"})
+ XY2, {'inst_x' : IR_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,6 +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_IMMUTABLE_ARRAY, IR_IMMUTABLE
from pypy.rpython import rvirtualizable2
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.unroll import unrolling_iterable
@@ -10,7 +11,7 @@
from pypy.jit.metainterp.warmstate import wrap, unwrap
from pypy.rlib.objectmodel import specialize
-class VirtualizableInfo:
+class VirtualizableInfo(object):
TOKEN_NONE = 0 # must be 0 -- see also x86.call_assembler
TOKEN_TRACING_RESCALL = -1
@@ -33,11 +34,13 @@
all_fields = accessor.fields
static_fields = []
array_fields = []
- for name, suffix in all_fields.iteritems():
- if suffix == '[*]':
+ for name, tp in all_fields.iteritems():
+ if tp == IR_IMMUTABLE_ARRAY:
array_fields.append(name)
+ elif tp == IR_IMMUTABLE:
+ static_fields.append(name)
else:
- static_fields.append(name)
+ raise Exception("unknown type: %s" % tp)
self.static_fields = static_fields
self.array_fields = array_fields
#
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -131,6 +131,16 @@
def find_set_param(graphs):
return _find_jit_marker(graphs, 'set_param')
+def find_force_quasi_immutable(graphs):
+ results = []
+ for graph in graphs:
+ for block in graph.iterblocks():
+ for i in range(len(block.operations)):
+ op = block.operations[i]
+ if op.opname == 'jit_force_quasi_immutable':
+ results.append((graph, block, i))
+ return results
+
def get_stats():
return pyjitpl._warmrunnerdesc.stats
@@ -187,6 +197,7 @@
self.rewrite_can_enter_jits()
self.rewrite_set_param()
self.rewrite_force_virtual(vrefinfo)
+ self.rewrite_force_quasi_immutable()
self.add_finish()
self.metainterp_sd.finish_setup(self.codewriter)
@@ -842,6 +853,28 @@
all_graphs = self.translator.graphs
vrefinfo.replace_force_virtual_with_call(all_graphs)
+ def replace_force_quasiimmut_with_direct_call(self, op):
+ ARG = op.args[0].concretetype
+ mutatefieldname = op.args[1].value
+ key = (ARG, mutatefieldname)
+ if key in self._cache_force_quasiimmed_funcs:
+ cptr = self._cache_force_quasiimmed_funcs[key]
+ else:
+ from pypy.jit.metainterp import quasiimmut
+ func = quasiimmut.make_invalidation_function(ARG, mutatefieldname)
+ FUNC = lltype.Ptr(lltype.FuncType([ARG], lltype.Void))
+ llptr = self.helper_func(FUNC, func)
+ cptr = Constant(llptr, FUNC)
+ self._cache_force_quasiimmed_funcs[key] = cptr
+ op.opname = 'direct_call'
+ op.args = [cptr, op.args[0]]
+
+ def rewrite_force_quasi_immutable(self):
+ self._cache_force_quasiimmed_funcs = {}
+ graphs = self.translator.graphs
+ for graph, block, i in find_force_quasi_immutable(graphs):
+ self.replace_force_quasiimmut_with_direct_call(block.operations[i])
+
# ____________________________________________________________
def execute_token(self, loop_token):
diff --git a/pypy/jit/tl/pypyjit.py b/pypy/jit/tl/pypyjit.py
--- a/pypy/jit/tl/pypyjit.py
+++ b/pypy/jit/tl/pypyjit.py
@@ -115,6 +115,8 @@
# print a message, and restart
unixcheckpoint.restartable_point(auto='run')
+ from pypy.jit.codewriter.codewriter import CodeWriter
+ CodeWriter.debug = True
from pypy.jit.tl.pypyjit_child import run_child, run_child_ootype
if BACKEND == 'c':
run_child(globals(), locals())
diff --git a/pypy/jit/tl/pypyjit_demo.py b/pypy/jit/tl/pypyjit_demo.py
--- a/pypy/jit/tl/pypyjit_demo.py
+++ b/pypy/jit/tl/pypyjit_demo.py
@@ -1,18 +1,11 @@
try:
- def g(x):
- return x - 1
def f(x):
- while x:
- x = g(x)
- import cProfile
- import time
- t1 = time.time()
- cProfile.run("f(10000000)")
- t2 = time.time()
- f(10000000)
- t3 = time.time()
- print t2 - t1, t3 - t2, (t3 - t2) / (t2 - t1)
+ i = 0
+ while i < x:
+ range(i)
+ i += 1
+ f(10000)
except Exception, e:
print "Exception: ", type(e)
print e
diff --git a/pypy/jit/tool/jitoutput.py b/pypy/jit/tool/jitoutput.py
--- a/pypy/jit/tool/jitoutput.py
+++ b/pypy/jit/tool/jitoutput.py
@@ -25,6 +25,7 @@
(('abort.compiling',), '^abort: compiling:\s+(\d+)$'),
(('abort.vable_escape',), '^abort: vable escape:\s+(\d+)$'),
(('abort.bad_loop',), '^abort: bad loop:\s+(\d+)$'),
+ (('abort.force_quasiimmut',), '^abort: force quasi-immut:\s+(\d+)$'),
(('nvirtuals',), '^nvirtuals:\s+(\d+)$'),
(('nvholes',), '^nvholes:\s+(\d+)$'),
(('nvreused',), '^nvreused:\s+(\d+)$'),
diff --git a/pypy/jit/tool/test/test_jitoutput.py b/pypy/jit/tool/test/test_jitoutput.py
--- a/pypy/jit/tool/test/test_jitoutput.py
+++ b/pypy/jit/tool/test/test_jitoutput.py
@@ -61,6 +61,7 @@
abort: compiling: 11
abort: vable escape: 12
abort: bad loop: 135
+abort: force quasi-immut: 3
nvirtuals: 13
nvholes: 14
nvreused: 15
@@ -89,6 +90,7 @@
assert info.abort.compiling == 11
assert info.abort.vable_escape == 12
assert info.abort.bad_loop == 135
+ assert info.abort.force_quasiimmut == 3
assert info.nvirtuals == 13
assert info.nvholes == 14
assert info.nvreused == 15
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -128,7 +128,7 @@
if op.name != 'debug_merge_point' or include_debug_merge_points:
yield op
- def allops(self, include_debug_merge_points=False, opcode=None):
+ def _allops(self, include_debug_merge_points=False, opcode=None):
opcode_name = opcode
for chunk in self.flatten_chunks():
opcode = chunk.getopcode()
@@ -136,6 +136,9 @@
for op in self._ops_for_chunk(chunk, include_debug_merge_points):
yield op
+ def allops(self, *args, **kwds):
+ return list(self._allops(*args, **kwds))
+
def format_ops(self, id=None, **kwds):
if id is None:
ops = self.allops(**kwds)
@@ -146,7 +149,7 @@
def print_ops(self, *args, **kwds):
print self.format_ops(*args, **kwds)
- def ops_by_id(self, id, include_debug_merge_points=False, opcode=None):
+ def _ops_by_id(self, id, include_debug_merge_points=False, opcode=None):
opcode_name = opcode
target_opcodes = self.ids[id]
for chunk in self.flatten_chunks():
@@ -156,6 +159,9 @@
for op in self._ops_for_chunk(chunk, include_debug_merge_points):
yield op
+ def ops_by_id(self, *args, **kwds):
+ return list(self._ops_by_id(*args, **kwds))
+
def match(self, expected_src, **kwds):
ops = list(self.allops())
matcher = OpMatcher(ops, src=self.format_ops())
@@ -167,6 +173,7 @@
return matcher.match(expected_src)
class InvalidMatch(Exception):
+ opindex = None
def __init__(self, message, frame):
Exception.__init__(self, message)
@@ -326,31 +333,39 @@
"""
iter_exp_ops = iter(expected_ops)
iter_ops = iter(self.ops)
- for exp_op in iter_exp_ops:
- if exp_op == '...':
- # loop until we find an operation which matches
- try:
- exp_op = iter_exp_ops.next()
- except StopIteration:
- # the ... is the last line in the expected_ops, so we just
- # return because it matches everything until the end
- return
- op = self.match_until(exp_op, iter_ops)
- else:
- while True:
- op = self._next_op(iter_ops)
- if op.name not in ignore_ops:
- break
- self.match_op(op, exp_op)
+ for opindex, exp_op in enumerate(iter_exp_ops):
+ try:
+ if exp_op == '...':
+ # loop until we find an operation which matches
+ try:
+ exp_op = iter_exp_ops.next()
+ except StopIteration:
+ # the ... is the last line in the expected_ops, so we just
+ # return because it matches everything until the end
+ return
+ op = self.match_until(exp_op, iter_ops)
+ else:
+ while True:
+ op = self._next_op(iter_ops)
+ if op.name not in ignore_ops:
+ break
+ self.match_op(op, exp_op)
+ except InvalidMatch, e:
+ e.opindex = opindex
+ raise
#
# make sure we exhausted iter_ops
self._next_op(iter_ops, assert_raises=True)
def match(self, expected_src, ignore_ops=[]):
- def format(src):
+ def format(src, opindex=None):
if src is None:
return ''
- return py.code.Source(src).deindent().indent()
+ text = str(py.code.Source(src).deindent().indent())
+ lines = text.splitlines(True)
+ if opindex is not None and 0 <= opindex < len(lines):
+ lines[opindex] = lines[opindex].rstrip() + '\t<=====\n'
+ return ''.join(lines)
#
expected_src = self.preprocess_expected_src(expected_src)
expected_ops = self.parse_ops(expected_src)
@@ -366,7 +381,7 @@
print
print "Ignore ops:", ignore_ops
print "Got:"
- print format(self.src)
+ print format(self.src, e.opindex)
print
print "Expected:"
print format(expected_src)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_model.py b/pypy/module/pypyjit/test_pypy_c/test_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_model.py
@@ -468,11 +468,13 @@
log = self.run(f)
loop, = log.loops_by_id('ntohs')
assert loop.match_by_id('ntohs', """
+ guard_not_invalidated(descr=...)
p12 = call(ConstClass(ntohs), 1, descr=...)
guard_no_exception(descr=...)
""")
#
assert not loop.match_by_id('ntohs', """
+ guard_not_invalidated(descr=...)
p12 = call(ConstClass(foobar), 1, descr=...)
guard_no_exception(descr=...)
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -221,7 +221,7 @@
entry_bridge, = log.loops_by_filename(self.filepath, is_entry_bridge=True)
ops = entry_bridge.ops_by_id('meth1', opcode='LOOKUP_METHOD')
assert log.opnames(ops) == ['guard_value', 'getfield_gc', 'guard_value',
- 'getfield_gc', 'guard_value']
+ 'guard_not_invalidated']
# the second LOOKUP_METHOD is folded away
assert list(entry_bridge.ops_by_id('meth2', opcode='LOOKUP_METHOD')) == []
#
@@ -231,14 +231,15 @@
assert loop.match("""
i15 = int_lt(i6, i9)
guard_true(i15, descr=)
+ guard_not_invalidated(descr=)
i16 = force_token()
i17 = int_add_ovf(i10, i6)
- guard_no_overflow(descr=)
+ guard_no_overflow(descr=)
i18 = force_token()
i19 = int_add_ovf(i10, i17)
- guard_no_overflow(descr=)
+ guard_no_overflow(descr=)
--TICK--
- jump(p0, p1, p2, p3, p4, p5, i19, p7, i17, i9, i10, p11, p12, p13, p14, descr=)
+ jump(p0, p1, p2, p3, p4, p5, i19, p7, i17, i9, i10, p11, p12, p13, descr=)
""")
def test_static_classmethod_call(self):
@@ -264,17 +265,17 @@
assert loop.match("""
i14 = int_lt(i6, i9)
guard_true(i14, descr=)
+ guard_not_invalidated(descr=)
i15 = force_token()
i17 = int_add_ovf(i8, 1)
- guard_no_overflow(descr=)
+ guard_no_overflow(descr=)
i18 = force_token()
i20 = int_sub(i17, 1)
--TICK--
- jump(p0, p1, p2, p3, p4, p5, i20, p7, i17, i9, p10, p11, p12, p13, descr=)
+ jump(p0, p1, p2, p3, p4, p5, i20, p7, i17, i9, p10, p11, p12, descr=)
""")
def test_default_and_kw(self):
- py.test.skip("Wait until we have saner defaults strat")
def main(n):
def f(i, j=1):
return i + j
@@ -415,8 +416,9 @@
assert loop.match("""
i7 = int_lt(i5, i6)
guard_true(i7, descr=)
+ guard_not_invalidated(descr=)
i9 = int_add_ovf(i5, 2)
- guard_no_overflow(descr=)
+ guard_no_overflow(descr=)
--TICK--
jump(p0, p1, p2, p3, p4, i9, i6, descr=)
""")
@@ -439,10 +441,11 @@
assert loop.match("""
i9 = int_lt(i5, i6)
guard_true(i9, descr=)
+ guard_not_invalidated(descr=)
i10 = int_add_ovf(i5, i7)
- guard_no_overflow(descr=)
+ guard_no_overflow(descr=)
--TICK--
- jump(p0, p1, p2, p3, p4, i10, i6, i7, p8, descr=)
+ jump(p0, p1, p2, p3, p4, i10, i6, p7, i7, p8, descr=)
""")
def test_mixed_type_loop(self):
@@ -506,15 +509,15 @@
i20 = int_add(i11, 1)
i21 = force_token()
setfield_gc(p4, i20, descr=<.* .*W_AbstractSeqIterObject.inst_index .*>)
+ guard_not_invalidated(descr=)
i23 = int_lt(i18, 0)
- guard_false(i23, descr=)
+ guard_false(i23, descr=)
i25 = int_ge(i18, i9)
- guard_false(i25, descr=)
- i26 = int_mul(i18, i10)
- i27 = int_add_ovf(i7, i26)
- guard_no_overflow(descr=)
+ guard_false(i25, descr=)
+ i27 = int_add_ovf(i7, i18)
+ guard_no_overflow(descr=)
--TICK--
- jump(p0, p1, p2, p3, p4, p5, p6, i27, i18, i9, i10, i20, i12, p13, i14, i15, descr=)
+ jump(..., descr=)
""")
def test_exception_inside_loop_1(self):
@@ -533,11 +536,12 @@
assert loop.match("""
i5 = int_is_true(i3)
guard_true(i5, descr=)
+ guard_not_invalidated(descr=)
--EXC-TICK--
i12 = int_sub_ovf(i3, 1)
- guard_no_overflow(descr=)
+ guard_no_overflow(descr=)
--TICK--
- jump(p0, p1, p2, i12, descr=)
+ jump(..., descr=)
""")
def test_exception_inside_loop_2(self):
@@ -580,10 +584,11 @@
assert loop.match("""
i7 = int_lt(i4, i5)
guard_true(i7, descr=)
+ guard_not_invalidated(descr=)
--EXC-TICK--
i14 = int_add(i4, 1)
--TICK--
- jump(p0, p1, p2, p3, i14, i5, descr=)
+ jump(..., descr=)
""")
def test_chain_of_guards(self):
@@ -685,10 +690,11 @@
assert loop.match_by_id('import', """
p11 = getfield_gc(ConstPtr(ptr10), descr=)
guard_value(p11, ConstPtr(ptr12), descr=)
+ guard_not_invalidated(descr=)
p14 = getfield_gc(ConstPtr(ptr13), descr=)
p16 = getfield_gc(ConstPtr(ptr15), descr=)
- guard_value(p14, ConstPtr(ptr17), descr=)
- guard_isnull(p16, descr=)
+ guard_value(p14, ConstPtr(ptr17), descr=)
+ guard_isnull(p16, descr=)
""")
def test_import_fast_path(self, tmpdir):
@@ -1109,7 +1115,7 @@
# -------------------------------
entry_bridge, = log.loops_by_filename(self.filepath, is_entry_bridge=True)
ops = entry_bridge.ops_by_id('mutate', opcode='LOAD_ATTR')
- assert log.opnames(ops) == ['guard_value', 'getfield_gc', 'guard_value',
+ assert log.opnames(ops) == ['guard_value', 'guard_not_invalidated',
'getfield_gc', 'guard_nonnull_class']
# the STORE_ATTR is folded away
assert list(entry_bridge.ops_by_id('meth1', opcode='STORE_ATTR')) == []
@@ -1121,6 +1127,7 @@
i8 = getfield_gc_pure(p5, descr=)
i9 = int_lt(i8, i7)
guard_true(i9, descr=.*)
+ guard_not_invalidated(descr=.*)
i11 = int_add(i8, 1)
i12 = force_token()
--TICK--
diff --git a/pypy/objspace/std/boolobject.py b/pypy/objspace/std/boolobject.py
--- a/pypy/objspace/std/boolobject.py
+++ b/pypy/objspace/std/boolobject.py
@@ -5,8 +5,7 @@
class W_BoolObject(W_Object):
from pypy.objspace.std.booltype import bool_typedef as typedef
-
- _immutable_ = True
+ _immutable_fields_ = ['boolval']
def __init__(w_self, boolval):
w_self.boolval = not not boolval
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -22,7 +22,6 @@
from pypy.interpreter import gateway
from pypy.interpreter.argument import Signature
from pypy.interpreter.buffer import RWBuffer
-from pypy.interpreter.function import Defaults
from pypy.objspace.std.bytearraytype import (
makebytearraydata_w, getbytevalue,
new_bytearray
@@ -43,7 +42,7 @@
registerimplementation(W_BytearrayObject)
init_signature = Signature(['source', 'encoding', 'errors'], None, None)
-init_defaults = Defaults([None, None, None])
+init_defaults = [None, None, None]
def init__Bytearray(space, w_bytearray, __args__):
# this is on the silly side
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -4,7 +4,6 @@
from pypy.interpreter import gateway
from pypy.interpreter.argument import Signature
from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.function import Defaults
from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX, OPTIMIZED_BUILTINS
from pypy.rlib.objectmodel import r_dict, we_are_translated
@@ -617,7 +616,7 @@
init_signature = Signature(['seq_or_map'], None, 'kwargs')
-init_defaults = Defaults([None])
+init_defaults = [None]
def update1(space, w_dict, w_data):
if space.findattr(w_data, space.wrap("keys")) is None:
diff --git a/pypy/objspace/std/fake.py b/pypy/objspace/std/fake.py
--- a/pypy/objspace/std/fake.py
+++ b/pypy/objspace/std/fake.py
@@ -144,7 +144,7 @@
frame = func.space.createframe(self, func.w_func_globals,
func.closure)
sig = self.signature()
- scope_w = args.parse_obj(None, func.name, sig, func.defs.getitems())
+ scope_w = args.parse_obj(None, func.name, sig, func.defs_w)
frame.setfastscope(scope_w)
return frame.run()
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -8,7 +8,6 @@
from pypy.objspace.std import slicetype
from pypy.interpreter import gateway, baseobjspace
-from pypy.interpreter.function import Defaults
from pypy.rlib.listsort import TimSort
from pypy.interpreter.argument import Signature
@@ -33,7 +32,7 @@
init_signature = Signature(['sequence'], None, None)
-init_defaults = Defaults([None])
+init_defaults = [None]
def init__List(space, w_list, __args__):
from pypy.objspace.std.tupleobject import W_TupleObject
diff --git a/pypy/objspace/std/noneobject.py b/pypy/objspace/std/noneobject.py
--- a/pypy/objspace/std/noneobject.py
+++ b/pypy/objspace/std/noneobject.py
@@ -9,7 +9,6 @@
class W_NoneObject(W_Object):
from pypy.objspace.std.nonetype import none_typedef as typedef
- _immutable_ = True
def unwrap(w_self, space):
return None
diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py
--- a/pypy/objspace/std/setobject.py
+++ b/pypy/objspace/std/setobject.py
@@ -5,7 +5,6 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter import gateway
from pypy.interpreter.argument import Signature
-from pypy.interpreter.function import Defaults
from pypy.objspace.std.settype import set_typedef as settypedef
from pypy.objspace.std.frozensettype import frozenset_typedef as frozensettypedef
@@ -625,7 +624,7 @@
cmp__Frozenset_frozensettypedef = cmp__Set_settypedef
init_signature = Signature(['some_iterable'], None, None)
-init_defaults = Defaults([None])
+init_defaults = [None]
def init__Set(space, w_set, __args__):
w_iterable, = __args__.parse_obj(
None, 'set',
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -88,13 +88,14 @@
_immutable_fields_ = ["flag_heaptype",
"flag_cpytype",
- # flag_abstract is not immutable
+ "flag_abstract?",
'needsdel',
'weakrefable',
'hasdict',
'nslots',
'instancetypedef',
'terminator',
+ '_version_tag?',
]
# for config.objspace.std.getattributeshortcut
diff --git a/pypy/rpython/annlowlevel.py b/pypy/rpython/annlowlevel.py
--- a/pypy/rpython/annlowlevel.py
+++ b/pypy/rpython/annlowlevel.py
@@ -480,7 +480,26 @@
# ____________________________________________________________
def cast_object_to_ptr(PTR, object):
- raise NotImplementedError("cast_object_to_ptr")
+ """NOT_RPYTHON: hack. The object may be disguised as a PTR now.
+ Limited to casting a given object to a single type.
+ """
+ if isinstance(PTR, lltype.Ptr):
+ TO = PTR.TO
+ else:
+ TO = PTR
+ if not hasattr(object, '_carry_around_for_tests'):
+ assert not hasattr(object, '_TYPE')
+ object._carry_around_for_tests = True
+ object._TYPE = TO
+ else:
+ assert object._TYPE == TO
+ #
+ if isinstance(PTR, lltype.Ptr):
+ return lltype._ptr(PTR, object, True)
+ elif isinstance(PTR, ootype.Instance):
+ return object
+ else:
+ raise NotImplementedError("cast_object_to_ptr(%r, ...)" % PTR)
def cast_instance_to_base_ptr(instance):
return cast_object_to_ptr(base_ptr_lltype(), instance)
@@ -535,7 +554,13 @@
# ____________________________________________________________
def cast_base_ptr_to_instance(Class, ptr):
- raise NotImplementedError("cast_base_ptr_to_instance")
+ """NOT_RPYTHON: hack. Reverse the hacking done in cast_object_to_ptr()."""
+ if isinstance(lltype.typeOf(ptr), lltype.Ptr):
+ ptr = ptr._as_obj()
+ if not isinstance(ptr, Class):
+ raise NotImplementedError("cast_base_ptr_to_instance: casting %r to %r"
+ % (ptr, Class))
+ return ptr
class CastBasePtrToInstanceEntry(extregistry.ExtRegistryEntry):
_about_ = cast_base_ptr_to_instance
diff --git a/pypy/rpython/callparse.py b/pypy/rpython/callparse.py
--- a/pypy/rpython/callparse.py
+++ b/pypy/rpython/callparse.py
@@ -1,5 +1,4 @@
from pypy.interpreter.argument import ArgumentsForTranslation, ArgErr
-from pypy.interpreter.function import Defaults
from pypy.annotation import model as annmodel
from pypy.rpython import rtuple
from pypy.rpython.error import TyperError
@@ -53,7 +52,7 @@
for x in graph.defaults:
defs_h.append(ConstHolder(x))
try:
- holders = arguments.match_signature(signature, Defaults(defs_h))
+ holders = arguments.match_signature(signature, defs_h)
except ArgErr, e:
raise TyperError, "signature mismatch: %s" % e.getmsg(graph.name)
diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -578,6 +578,7 @@
_all_callbacks_results = []
_int2obj = {}
_callback_exc_info = None
+_opaque_objs = [None]
def get_rtyper():
llinterp = LLInterpreter.current_interpreter
@@ -616,6 +617,10 @@
T = lltype.Ptr(lltype.typeOf(container))
# otherwise it came from integer and we want a c_void_p with
# the same valu
+ if getattr(container, 'llopaque', None):
+ no = len(_opaque_objs)
+ _opaque_objs.append(container)
+ return no * 2 + 1
else:
container = llobj._obj
if isinstance(T.TO, lltype.FuncType):
@@ -764,10 +769,14 @@
if isinstance(T, lltype.Typedef):
T = T.OF
if isinstance(T, lltype.Ptr):
- if not cobj or not ctypes.cast(cobj, ctypes.c_void_p).value: # NULL pointer
+ ptrval = ctypes.cast(cobj, ctypes.c_void_p).value
+ if not cobj or not ptrval: # NULL pointer
# CFunctionType.__nonzero__ is broken before Python 2.6
return lltype.nullptr(T.TO)
if isinstance(T.TO, lltype.Struct):
+ if ptrval & 1: # a tagged pointer
+ gcref = _opaque_objs[ptrval // 2].hide()
+ return lltype.cast_opaque_ptr(T, gcref)
REAL_TYPE = T.TO
if T.TO._arrayfld is not None:
carray = getattr(cobj.contents, T.TO._arrayfld)
@@ -1228,7 +1237,9 @@
return not self == other
def _cast_to_ptr(self, PTRTYPE):
- return force_cast(PTRTYPE, self.intval)
+ if self.intval & 1:
+ return _opaque_objs[self.intval // 2]
+ return force_cast(PTRTYPE, self.intval)
## def _cast_to_int(self):
## return self.intval
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -433,6 +433,7 @@
'jit_marker': LLOp(),
'jit_force_virtualizable':LLOp(canrun=True),
'jit_force_virtual': LLOp(canrun=True),
+ 'jit_force_quasi_immutable': LLOp(canrun=True),
'get_exception_addr': LLOp(),
'get_exc_value_addr': LLOp(),
'do_malloc_fixedsize_clear':LLOp(canraise=(MemoryError,),canunwindgc=True),
diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -341,13 +341,14 @@
return _struct(self, n, initialization='example')
def _immutable_field(self, field):
+ if self._hints.get('immutable'):
+ return True
if 'immutable_fields' in self._hints:
try:
- s = self._hints['immutable_fields'].fields[field]
- return s or True
+ return self._hints['immutable_fields'].fields[field]
except KeyError:
pass
- return self._hints.get('immutable', False)
+ return False
class RttiStruct(Struct):
_runtime_type_info = None
@@ -1029,6 +1030,8 @@
return None # null pointer
if type(p._obj0) is int:
return p # a pointer obtained by cast_int_to_ptr
+ if getattr(p._obj0, '_carry_around_for_tests', False):
+ return p # a pointer obtained by cast_instance_to_base_ptr
container = obj._normalizedcontainer()
if type(container) is int:
# this must be an opaque ptr originating from an integer
@@ -1881,8 +1884,8 @@
if self.__class__ is not other.__class__:
return NotImplemented
if hasattr(self, 'container') and hasattr(other, 'container'):
- obj1 = self.container._normalizedcontainer()
- obj2 = other.container._normalizedcontainer()
+ obj1 = self._normalizedcontainer()
+ obj2 = other._normalizedcontainer()
return obj1 == obj2
else:
return self is other
@@ -1906,6 +1909,8 @@
# an integer, cast to a ptr, cast to an opaque
if type(self.container) is int:
return self.container
+ if getattr(self.container, '_carry_around_for_tests', False):
+ return self.container
return self.container._normalizedcontainer()
else:
return _parentable._normalizedcontainer(self)
diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py
--- a/pypy/rpython/lltypesystem/opimpl.py
+++ b/pypy/rpython/lltypesystem/opimpl.py
@@ -525,6 +525,9 @@
def op_jit_force_virtual(x):
return x
+def op_jit_force_quasi_immutable(*args):
+ pass
+
def op_get_group_member(TYPE, grpptr, memberoffset):
from pypy.rpython.lltypesystem import llgroup
assert isinstance(memberoffset, llgroup.GroupMemberOffset)
diff --git a/pypy/rpython/lltypesystem/rclass.py b/pypy/rpython/lltypesystem/rclass.py
--- a/pypy/rpython/lltypesystem/rclass.py
+++ b/pypy/rpython/lltypesystem/rclass.py
@@ -322,6 +322,7 @@
# before they are fully built, to avoid strange bugs in case
# of recursion where other code would uses these
# partially-initialized dicts.
+ AbstractInstanceRepr._setup_repr(self)
self.rclass = getclassrepr(self.rtyper, self.classdef)
fields = {}
allinstancefields = {}
@@ -370,6 +371,11 @@
kwds = {}
if self.gcflavor == 'gc':
kwds['rtti'] = True
+
+ for name, attrdef in attrs:
+ if not attrdef.readonly and self.is_quasi_immutable(name):
+ llfields.append(('mutate_' + name, OBJECTPTR))
+
object_type = MkStruct(self.classdef.name,
('super', self.rbase.object_type),
hints=hints,
@@ -488,6 +494,7 @@
if force_cast:
vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
self.hook_access_field(vinst, cname, llops, flags)
+ self.hook_setfield(vinst, attr, llops)
llops.genop('setfield', [vinst, cname, vvalue])
else:
if self.classdef is None:
@@ -495,9 +502,6 @@
self.rbase.setfield(vinst, attr, vvalue, llops, force_cast=True,
flags=flags)
- def hook_access_field(self, vinst, cname, llops, flags):
- pass # for virtualizables; see rvirtualizable2.py
-
def new_instance(self, llops, classcallhop=None):
"""Build a new instance, without calling __init__."""
flavor = self.gcflavor
diff --git a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
--- a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
@@ -1293,6 +1293,28 @@
rffi.cast(SP, p).x = 0
lltype.free(chunk, flavor='raw')
+ def test_opaque_tagged_pointers(self):
+ from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+ from pypy.rpython.lltypesystem import rclass
+
+ class Opaque(object):
+ llopaque = True
+
+ def hide(self):
+ ptr = cast_instance_to_base_ptr(self)
+ return lltype.cast_opaque_ptr(llmemory.GCREF, ptr)
+
+ @staticmethod
+ def show(gcref):
+ ptr = lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT), gcref)
+ return cast_base_ptr_to_instance(Opaque, ptr)
+
+ opaque = Opaque()
+ round = ctypes2lltype(llmemory.GCREF, lltype2ctypes(opaque.hide()))
+ assert Opaque.show(round) is opaque
+
+
class TestPlatform(object):
def test_lib_on_libpaths(self):
from pypy.translator.platform import platform
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
@@ -54,6 +54,7 @@
def test_is_pure():
from pypy.objspace.flow.model import Variable, Constant
+ from pypy.rpython import rclass
assert llop.bool_not.is_pure([Variable()])
assert llop.debug_assert.is_pure([Variable()])
assert not llop.int_add_ovf.is_pure([Variable(), Variable()])
@@ -85,38 +86,52 @@
assert llop.getarrayitem.is_pure([v_a2, Variable()])
assert llop.getarraysize.is_pure([v_a2])
#
- accessor = rclass.FieldListAccessor()
- S3 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
- hints={'immutable_fields': accessor})
- accessor.initialize(S3, {'x': ''})
- v_s3 = Variable()
- v_s3.concretetype = lltype.Ptr(S3)
- assert not llop.setfield.is_pure([v_s3, Constant('x'), Variable()])
- assert not llop.setfield.is_pure([v_s3, Constant('y'), Variable()])
- assert llop.getfield.is_pure([v_s3, Constant('x')])
- assert not llop.getfield.is_pure([v_s3, Constant('y')])
+ for kind in [rclass.IR_MUTABLE, rclass.IR_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})
+ accessor.initialize(S3, {'x': kind})
+ v_s3 = Variable()
+ v_s3.concretetype = lltype.Ptr(S3)
+ assert not llop.setfield.is_pure([v_s3, Constant('x'), Variable()])
+ assert not llop.setfield.is_pure([v_s3, Constant('y'), Variable()])
+ assert llop.getfield.is_pure([v_s3, Constant('x')]) is kind
+ assert not llop.getfield.is_pure([v_s3, Constant('y')])
def test_getfield_pure():
S1 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed))
S2 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
hints={'immutable': True})
accessor = rclass.FieldListAccessor()
- S3 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
- hints={'immutable_fields': accessor})
- accessor.initialize(S3, {'x': ''})
#
s1 = lltype.malloc(S1); s1.x = 45
py.test.raises(TypeError, llop.getfield, lltype.Signed, s1, 'x')
s2 = lltype.malloc(S2); s2.x = 45
assert llop.getfield(lltype.Signed, s2, 'x') == 45
- s3 = lltype.malloc(S3); s3.x = 46; s3.y = 47
- assert llop.getfield(lltype.Signed, s3, 'x') == 46
- py.test.raises(TypeError, llop.getfield, lltype.Signed, s3, 'y')
#
py.test.raises(TypeError, llop.getinteriorfield, lltype.Signed, s1, 'x')
assert llop.getinteriorfield(lltype.Signed, s2, 'x') == 45
- assert llop.getinteriorfield(lltype.Signed, s3, 'x') == 46
- py.test.raises(TypeError, llop.getinteriorfield, lltype.Signed, s3, 'y')
+ #
+ for kind in [rclass.IR_MUTABLE, rclass.IR_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_IMMUTABLE_ARRAY]:
+ assert llop.getfield(lltype.Signed, s3, 'x') == 46
+ assert llop.getinteriorfield(lltype.Signed, s3, 'x') == 46
+ else:
+ py.test.raises(TypeError, llop.getfield, lltype.Signed, s3, 'x')
+ py.test.raises(TypeError, llop.getinteriorfield,
+ lltype.Signed, s3, 'x')
+ py.test.raises(TypeError, llop.getfield, lltype.Signed, s3, 'y')
+ py.test.raises(TypeError, llop.getinteriorfield,
+ lltype.Signed, s3, 'y')
# ___________________________________________________________________________
# This tests that the LLInterpreter and the LL_OPERATIONS tables are in sync.
diff --git a/pypy/rpython/lltypesystem/test/test_lltype.py b/pypy/rpython/lltypesystem/test/test_lltype.py
--- a/pypy/rpython/lltypesystem/test/test_lltype.py
+++ b/pypy/rpython/lltypesystem/test/test_lltype.py
@@ -794,15 +794,8 @@
def __init__(self, fields):
self.fields = fields
S = GcStruct('S', ('x', lltype.Signed),
- hints={'immutable_fields': FieldListAccessor({'x':''})})
- assert S._immutable_field('x') == True
- #
- class FieldListAccessor(object):
- def __init__(self, fields):
- self.fields = fields
- S = GcStruct('S', ('x', lltype.Signed),
- hints={'immutable_fields': FieldListAccessor({'x':'[*]'})})
- assert S._immutable_field('x') == '[*]'
+ hints={'immutable_fields': FieldListAccessor({'x': 1234})})
+ assert S._immutable_field('x') == 1234
def test_typedef():
T = Typedef(Signed, 'T')
diff --git a/pypy/rpython/ootypesystem/ootype.py b/pypy/rpython/ootypesystem/ootype.py
--- a/pypy/rpython/ootypesystem/ootype.py
+++ b/pypy/rpython/ootypesystem/ootype.py
@@ -268,13 +268,14 @@
return self._superclass._get_fields_with_default() + self._fields_with_default
def _immutable_field(self, field):
+ if self._hints.get('immutable'):
+ return True
if 'immutable_fields' in self._hints:
try:
- s = self._hints['immutable_fields'].fields[field]
- return s or True
+ return self._hints['immutable_fields'].fields[field]
except KeyError:
pass
- return self._hints.get('immutable', False)
+ return False
class SpecializableType(OOType):
diff --git a/pypy/rpython/ootypesystem/rclass.py b/pypy/rpython/ootypesystem/rclass.py
--- a/pypy/rpython/ootypesystem/rclass.py
+++ b/pypy/rpython/ootypesystem/rclass.py
@@ -262,6 +262,10 @@
self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef)
self.rbase.setup()
+ for name, attrdef in selfattrs.iteritems():
+ if not attrdef.readonly and self.is_quasi_immutable(name):
+ ootype.addFields(self.lowleveltype, {'mutable_'+name: OBJECT})
+
classattributes = {}
baseInstance = self.lowleveltype._superclass
classrepr = getclassrepr(self.rtyper, self.classdef)
@@ -476,11 +480,9 @@
mangled_name = mangle(attr, self.rtyper.getconfig())
cname = inputconst(ootype.Void, mangled_name)
self.hook_access_field(vinst, cname, llops, flags)
+ self.hook_setfield(vinst, attr, llops)
llops.genop('oosetfield', [vinst, cname, vvalue])
- def hook_access_field(self, vinst, cname, llops, flags):
- pass # for virtualizables; see rvirtualizable2.py
-
def rtype_is_true(self, hop):
vinst, = hop.inputargs(self)
return hop.genop('oononnull', [vinst], resulttype=ootype.Bool)
diff --git a/pypy/rpython/rclass.py b/pypy/rpython/rclass.py
--- a/pypy/rpython/rclass.py
+++ b/pypy/rpython/rclass.py
@@ -3,7 +3,8 @@
#from pypy.annotation.classdef import isclassdef
from pypy.annotation import description
from pypy.rpython.error import TyperError
-from pypy.rpython.rmodel import Repr, getgcflavor
+from pypy.rpython.rmodel import Repr, getgcflavor, inputconst
+from pypy.rpython.lltypesystem.lltype import Void
class FieldListAccessor(object):
@@ -12,6 +13,8 @@
assert type(fields) is dict
self.TYPE = TYPE
self.fields = fields
+ for x in fields.itervalues():
+ assert isinstance(x, ImmutableRanking)
def __repr__(self):
return '' % getattr(self, 'TYPE', '?')
@@ -19,6 +22,21 @@
def _freeze_(self):
return True
+class ImmutableRanking(object):
+ def __init__(self, name, is_immutable):
+ self.name = name
+ self.is_immutable = is_immutable
+ def __nonzero__(self):
+ return self.is_immutable
+ def __repr__(self):
+ return '<%s>' % self.name
+
+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
not consistent across a class hierarchy."""
@@ -155,7 +173,8 @@
self.classdef = classdef
def _setup_repr(self):
- pass
+ if self.classdef is None:
+ self.immutable_field_set = set()
def _check_for_immutable_hints(self, hints):
loc = self.classdef.classdesc.lookup('_immutable_')
@@ -167,13 +186,13 @@
self.classdef,))
hints = hints.copy()
hints['immutable'] = True
- self.immutable_field_list = [] # unless overwritten below
+ self.immutable_field_set = set() # unless overwritten below
if self.classdef.classdesc.lookup('_immutable_fields_') is not None:
hints = hints.copy()
immutable_fields = self.classdef.classdesc.classdict.get(
'_immutable_fields_')
if immutable_fields is not None:
- self.immutable_field_list = immutable_fields.value
+ self.immutable_field_set = set(immutable_fields.value)
accessor = FieldListAccessor()
hints['immutable_fields'] = accessor
return hints
@@ -201,33 +220,38 @@
if "immutable_fields" in hints:
accessor = hints["immutable_fields"]
if not hasattr(accessor, 'fields'):
- immutable_fields = []
+ immutable_fields = set()
rbase = self
while rbase.classdef is not None:
- immutable_fields += rbase.immutable_field_list
+ immutable_fields.update(rbase.immutable_field_set)
rbase = rbase.rbase
self._parse_field_list(immutable_fields, accessor)
def _parse_field_list(self, fields, accessor):
- with_suffix = {}
+ ranking = {}
for name in fields:
- if name.endswith('[*]'):
+ 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]
- suffix = '[*]'
- else:
- suffix = ''
+ rank = IR_IMMUTABLE_ARRAY
+ elif name.endswith('?'): # a quasi-immutable field
+ name = name[:-1]
+ rank = IR_QUASIIMMUTABLE
+ else: # a regular immutable/green field
+ rank = IR_IMMUTABLE
try:
mangled_name, r = self._get_field(name)
except KeyError:
continue
- with_suffix[mangled_name] = suffix
- accessor.initialize(self.object_type, with_suffix)
- return with_suffix
+ ranking[mangled_name] = rank
+ accessor.initialize(self.object_type, ranking)
+ return ranking
def _check_for_immutable_conflicts(self):
# check for conflicts, i.e. a field that is defined normally as
# mutable in some parent class but that is now declared immutable
- from pypy.rpython.lltypesystem.lltype import Void
is_self_immutable = "immutable" in self.object_type._hints
base = self
while base.classdef is not None:
@@ -248,12 +272,32 @@
"class %r has _immutable_=True, but parent class %r "
"defines (at least) the mutable field %r" % (
self, base, fieldname))
- if fieldname in self.immutable_field_list:
+ if (fieldname in self.immutable_field_set or
+ (fieldname + '?') in self.immutable_field_set):
raise ImmutableConflictError(
"field %r is defined mutable in class %r, but "
"listed in _immutable_fields_ in subclass %r" % (
fieldname, base, self))
+ def hook_access_field(self, vinst, cname, llops, flags):
+ pass # for virtualizables; see rvirtualizable2.py
+
+ def hook_setfield(self, vinst, fieldname, llops):
+ if self.is_quasi_immutable(fieldname):
+ c_fieldname = inputconst(Void, 'mutate_' + fieldname)
+ llops.genop('jit_force_quasi_immutable', [vinst, c_fieldname])
+
+ def is_quasi_immutable(self, fieldname):
+ search1 = fieldname + '?'
+ search2 = fieldname + '?[*]'
+ rbase = self
+ while rbase.classdef is not None:
+ if (search1 in rbase.immutable_field_set or
+ search2 in rbase.immutable_field_set):
+ return True
+ rbase = rbase.rbase
+ return False
+
def new_instance(self, llops, classcallhop=None):
raise NotImplementedError
diff --git a/pypy/rpython/rvirtualizable2.py b/pypy/rpython/rvirtualizable2.py
--- a/pypy/rpython/rvirtualizable2.py
+++ b/pypy/rpython/rvirtualizable2.py
@@ -50,7 +50,7 @@
def hook_access_field(self, vinst, cname, llops, flags):
#if not flags.get('access_directly'):
- if cname.value in self.my_redirected_fields:
+ if self.my_redirected_fields.get(cname.value):
cflags = inputconst(lltype.Void, flags)
llops.genop('jit_force_virtualizable', [vinst, cname, cflags])
diff --git a/pypy/rpython/test/test_annlowlevel.py b/pypy/rpython/test/test_annlowlevel.py
--- a/pypy/rpython/test/test_annlowlevel.py
+++ b/pypy/rpython/test/test_annlowlevel.py
@@ -4,9 +4,12 @@
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
from pypy.rpython.lltypesystem.rstr import mallocstr, mallocunicode
+from pypy.rpython.lltypesystem import lltype
from pypy.rpython.ootypesystem import ootype
from pypy.rpython.annlowlevel import hlstr, llstr, oostr
from pypy.rpython.annlowlevel import hlunicode, llunicode
+from pypy.rpython import annlowlevel
+
class TestLLType(BaseRtypingTest, LLRtypeMixin):
def test_hlstr(self):
@@ -53,6 +56,15 @@
res = self.interpret(f, [self.unicode_to_ll(u"abc")])
assert res == 3
+ def test_cast_instance_to_base_ptr(self):
+ class X(object):
+ pass
+ x = X()
+ ptr = annlowlevel.cast_instance_to_base_ptr(x)
+ assert lltype.typeOf(ptr) == annlowlevel.base_ptr_lltype()
+ y = annlowlevel.cast_base_ptr_to_instance(X, ptr)
+ assert y is x
+
class TestOOType(BaseRtypingTest, OORtypeMixin):
def test_hlstr(self):
@@ -71,3 +83,12 @@
res = self.interpret(f, [self.string_to_ll("abc")])
assert res == 3
+
+ def test_cast_instance_to_base_obj(self):
+ class X(object):
+ pass
+ x = X()
+ obj = annlowlevel.cast_instance_to_base_obj(x)
+ assert lltype.typeOf(obj) == annlowlevel.base_obj_ootype()
+ y = annlowlevel.cast_base_ptr_to_instance(X, obj)
+ assert y is x
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,6 +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_IMMUTABLE_ARRAY
+from pypy.rpython.rclass import IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY
from pypy.objspace.flow.model import summary
class EmptyBase(object):
@@ -746,8 +748,10 @@
t, typer, graph = self.gengraph(f, [])
A_TYPE = deref(graph.getreturnvar().concretetype)
accessor = A_TYPE._hints["immutable_fields"]
- assert accessor.fields == {"inst_x" : "", "inst_y" : "[*]"} or \
- accessor.fields == {"ox" : "", "oy" : "[*]"} # for ootype
+ assert accessor.fields == {"inst_x": IR_IMMUTABLE,
+ "inst_y": IR_IMMUTABLE_ARRAY} or \
+ accessor.fields == {"ox": IR_IMMUTABLE,
+ "oy": IR_IMMUTABLE_ARRAY} # for ootype
def test_immutable_fields_subclass_1(self):
from pypy.jit.metainterp.typesystem import deref
@@ -765,8 +769,8 @@
t, typer, graph = self.gengraph(f, [])
B_TYPE = deref(graph.getreturnvar().concretetype)
accessor = B_TYPE._hints["immutable_fields"]
- assert accessor.fields == {"inst_x" : ""} or \
- accessor.fields == {"ox" : ""} # for ootype
+ assert accessor.fields == {"inst_x": IR_IMMUTABLE} or \
+ accessor.fields == {"ox": IR_IMMUTABLE} # for ootype
def test_immutable_fields_subclass_2(self):
from pypy.jit.metainterp.typesystem import deref
@@ -785,8 +789,10 @@
t, typer, graph = self.gengraph(f, [])
B_TYPE = deref(graph.getreturnvar().concretetype)
accessor = B_TYPE._hints["immutable_fields"]
- assert accessor.fields == {"inst_x" : "", "inst_y" : ""} or \
- accessor.fields == {"ox" : "", "oy" : ""} # for ootype
+ assert accessor.fields == {"inst_x": IR_IMMUTABLE,
+ "inst_y": IR_IMMUTABLE} or \
+ accessor.fields == {"ox": IR_IMMUTABLE,
+ "oy": IR_IMMUTABLE} # for ootype
def test_immutable_fields_only_in_subclass(self):
from pypy.jit.metainterp.typesystem import deref
@@ -804,8 +810,8 @@
t, typer, graph = self.gengraph(f, [])
B_TYPE = deref(graph.getreturnvar().concretetype)
accessor = B_TYPE._hints["immutable_fields"]
- assert accessor.fields == {"inst_y" : ""} or \
- accessor.fields == {"oy" : ""} # for ootype
+ assert accessor.fields == {"inst_y": IR_IMMUTABLE} or \
+ accessor.fields == {"oy": IR_IMMUTABLE} # for ootype
def test_immutable_forbidden_inheritance_1(self):
from pypy.rpython.rclass import ImmutableConflictError
@@ -849,8 +855,8 @@
except AttributeError:
A_TYPE = B_TYPE._superclass # for ootype
accessor = A_TYPE._hints["immutable_fields"]
- assert accessor.fields == {"inst_v" : ""} or \
- accessor.fields == {"ov" : ""} # for ootype
+ assert accessor.fields == {"inst_v": IR_IMMUTABLE} or \
+ accessor.fields == {"ov": IR_IMMUTABLE} # for ootype
def test_immutable_subclass_1(self):
from pypy.rpython.rclass import ImmutableConflictError
@@ -895,6 +901,58 @@
B_TYPE = deref(graph.getreturnvar().concretetype)
assert B_TYPE._hints["immutable"]
+ def test_quasi_immutable(self):
+ from pypy.jit.metainterp.typesystem import deref
+ class A(object):
+ _immutable_fields_ = ['x', 'y', 'a?', 'b?']
+ class B(A):
+ pass
+ def f():
+ a = A()
+ a.x = 42
+ a.a = 142
+ b = B()
+ b.x = 43
+ b.y = 41
+ b.a = 44
+ b.b = 45
+ return B()
+ t, typer, graph = self.gengraph(f, [])
+ B_TYPE = deref(graph.getreturnvar().concretetype)
+ accessor = B_TYPE._hints["immutable_fields"]
+ assert accessor.fields == {"inst_y": IR_IMMUTABLE,
+ "inst_b": IR_QUASIIMMUTABLE} or \
+ accessor.fields == {"ox": IR_IMMUTABLE,
+ "oy": IR_IMMUTABLE,
+ "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,6 +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_IMMUTABLE_ARRAY
from pypy import conftest
@@ -116,8 +117,8 @@
TYPE = self.gettype(v_inst)
accessor = TYPE._hints['virtualizable2_accessor']
assert accessor.TYPE == TYPE
- assert accessor.fields == {self.prefix + 'v1' : "",
- self.prefix + 'v2': "[*]"}
+ assert accessor.fields == {self.prefix + 'v1': IR_IMMUTABLE,
+ self.prefix + 'v2': IR_IMMUTABLE_ARRAY}
#
def fn2(n):
Base().base1 = 42
diff --git a/pypy/translator/geninterplevel.py b/pypy/translator/geninterplevel.py
--- a/pypy/translator/geninterplevel.py
+++ b/pypy/translator/geninterplevel.py
@@ -71,7 +71,7 @@
log = py.log.Producer("geninterp")
py.log.setconsumer("geninterp", ansi_log)
-GI_VERSION = '1.2.8' # bump this for substantial changes
+GI_VERSION = '1.2.9' # bump this for substantial changes
# ____________________________________________________________
try:
@@ -1175,8 +1175,7 @@
pass
defaultsname = self.uniquename('default')
self._defaults_cache[key] = defaultsname
- self.initcode.append("from pypy.interpreter.function import Defaults")
- self.initcode.append("%s = Defaults([%s])" % (defaultsname, ', '.join(names)))
+ self.initcode.append("%s = [%s]" % (defaultsname, ', '.join(names)))
return defaultsname
def gen_rpyfunction(self, func):
From commits-noreply at bitbucket.org Sun May 8 16:01:32 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 16:01:32 +0200 (CEST)
Subject: [pypy-svn] pypy out-of-line-guards-2: close branch
Message-ID: <20110508140132.6ED382A2036@codespeak.net>
Author: Armin Rigo
Branch: out-of-line-guards-2
Changeset: r43946:1e461296ead8
Date: 2011-05-08 15:46 +0200
http://bitbucket.org/pypy/pypy/changeset/1e461296ead8/
Log: close branch
From commits-noreply at bitbucket.org Sun May 8 16:01:36 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 16:01:36 +0200 (CEST)
Subject: [pypy-svn] pypy merge-stdlib: Close this branch;
we're not going to merge 2.7 and modified-2.7
Message-ID: <20110508140136.56E7B2A203C@codespeak.net>
Author: Armin Rigo
Branch: merge-stdlib
Changeset: r43947:792b97143aea
Date: 2011-05-08 15:49 +0200
http://bitbucket.org/pypy/pypy/changeset/792b97143aea/
Log: Close this branch; we're not going to merge 2.7 and modified-2.7
right now.
From commits-noreply at bitbucket.org Sun May 8 17:23:26 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:23:26 +0200 (CEST)
Subject: [pypy-svn] pypy default: A tool to use from time to time,
to merge closed branches into the
Message-ID: <20110508152326.4DC062A2036@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43953:dbfc857ed8fd
Date: 2011-05-08 17:23 +0200
http://bitbucket.org/pypy/pypy/changeset/dbfc857ed8fd/
Log: A tool to use from time to time, to merge closed branches into the
branch called 'closed-branches'.
diff --git a/pypy/tool/clean_old_branches.py b/pypy/tool/clean_old_branches.py
new file mode 100644
--- /dev/null
+++ b/pypy/tool/clean_old_branches.py
@@ -0,0 +1,72 @@
+"""
+For branches that have been closed but still have a dangling head
+in 'hg heads --topo --closed', force them to join with the branch
+called 'closed-branch'. It reduces the number of heads.
+"""
+
+import os, sys
+
+if not os.listdir('.hg'):
+ print 'Must run this script from the top-level directory.'
+ sys.exit(1)
+
+def heads(args):
+ g = os.popen(r"hg heads --topo %s --template '{branches} {node|short}\n'"
+ % args, 'r')
+ result = g.read()
+ g.close()
+ result = result.splitlines(False)
+ result = [s for s in result
+ if not s.startswith(' ')
+ and not s.startswith('closed-branches ')]
+ return result
+
+all_heads = heads("--closed")
+opened_heads = heads("")
+
+closed_heads = [s for s in all_heads if s not in opened_heads]
+
+if not closed_heads:
+ print >> sys.stderr, 'no dangling closed heads.'
+ sys.exit()
+
+# ____________________________________________________________
+
+closed_heads = sorted(set(closed_heads))
+
+for branch_head in closed_heads:
+ branch, head = branch_head.split()
+ print '\t', branch
+print
+print 'The branches listed above will be merged to "closed-branches".'
+print 'You need to run this script in a clean working copy where you'
+print 'don''t mind all files being removed.'
+print
+if raw_input('Continue? [y/n] ').upper() != 'Y':
+ sys.exit(1)
+
+# ____________________________________________________________
+
+def do(cmd):
+ print cmd
+ err = os.system(cmd)
+ if err != 0:
+ print '*** error %r' % (err,)
+ sys.exit(1)
+
+for branch_head in closed_heads:
+ branch, head = branch_head.split()
+ print
+ print '***** %s ***** %s *****' % (branch, head)
+ do("hg up --clean closed-branches")
+ do("hg --config extensions.purge= purge --all")
+ do("hg merge -y %s" % head)
+ for fn in os.listdir('.'):
+ if fn.lower() != '.hg':
+ do("rm -fr -- '%s'" % fn)
+ do("hg rm --after -- '%s' || true" % fn)
+ do("hg ci -m'Merge closed head %s on branch %s'" % (head, branch))
+
+print
+do("hg ci --close-branch -m're-close this branch'")
+do("hg up default")
From commits-noreply at bitbucket.org Sun May 8 17:53:32 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:32 +0200 (CEST)
Subject: [pypy-svn] pypy default: Instead of sorting on the branch name,
use oldest-to-newest order.
Message-ID: <20110508155332.207B836C20F@codespeak.net>
Author: Armin Rigo
Branch:
Changeset: r43954:cfe9d8b0f6d6
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/cfe9d8b0f6d6/
Log: Instead of sorting on the branch name, use oldest-to-newest order.
diff --git a/pypy/tool/clean_old_branches.py b/pypy/tool/clean_old_branches.py
--- a/pypy/tool/clean_old_branches.py
+++ b/pypy/tool/clean_old_branches.py
@@ -32,7 +32,7 @@
# ____________________________________________________________
-closed_heads = sorted(set(closed_heads))
+closed_heads.reverse()
for branch_head in closed_heads:
branch, head = branch_head.split()
From commits-noreply at bitbucket.org Sun May 8 17:53:33 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:33 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 1e2af49d893d on
branch cpyext-2.5-backport
Message-ID: <20110508155333.96BAA36C210@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43955:854e7b2483b3
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/854e7b2483b3/
Log: Merge closed head 1e2af49d893d on branch cpyext-2.5-backport
From commits-noreply at bitbucket.org Sun May 8 17:53:35 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:35 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head d6cf549e7f91 on
branch minimark-jit
Message-ID: <20110508155335.9EECD2A2037@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43956:0e6bfc2ab6b4
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/0e6bfc2ab6b4/
Log: Merge closed head d6cf549e7f91 on branch minimark-jit
From commits-noreply at bitbucket.org Sun May 8 17:53:36 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:36 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head c1bac442ad90 on
branch jit-str
Message-ID: <20110508155336.B61372A2037@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43957:d9f12f96ac80
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/d9f12f96ac80/
Log: Merge closed head c1bac442ad90 on branch jit-str
From commits-noreply at bitbucket.org Sun May 8 17:53:38 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:38 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 2b4147978527 on
branch jit-free
Message-ID: <20110508155338.11E6C36C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43958:ec943df3658f
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/ec943df3658f/
Log: Merge closed head 2b4147978527 on branch jit-free
From commits-noreply at bitbucket.org Sun May 8 17:53:40 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:40 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head fe07543a0b4e on
branch gc-minimark-largeobj
Message-ID: <20110508155340.E13932A2036@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43959:fb429e4f28bd
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/fb429e4f28bd/
Log: Merge closed head fe07543a0b4e on branch gc-minimark-largeobj
diff --git a/.hgsubstate b/.hgsubstate
new file mode 100644
From commits-noreply at bitbucket.org Sun May 8 17:53:42 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:42 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 58e3b16331b7 on
branch smalllong
Message-ID: <20110508155342.2A27A2A2036@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43960:6599b08e22b9
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/6599b08e22b9/
Log: Merge closed head 58e3b16331b7 on branch smalllong
diff --git a/.hgsubstate b/.hgsubstate
deleted file mode 100644
From commits-noreply at bitbucket.org Sun May 8 17:53:43 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:43 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 785ddbf40836 on
branch simplify-conftest
Message-ID: <20110508155343.B8E562A2042@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43961:94cc2dd88bd5
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/94cc2dd88bd5/
Log: Merge closed head 785ddbf40836 on branch simplify-conftest
diff --git a/.hgsubstate b/.hgsubstate
new file mode 100644
From commits-noreply at bitbucket.org Sun May 8 17:53:45 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:45 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head c13b581ca33f on
branch fast-forward
Message-ID: <20110508155345.B36482A203B@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43962:2851921760fd
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/2851921760fd/
Log: Merge closed head c13b581ca33f on branch fast-forward
diff --git a/.hgsubstate b/.hgsubstate
deleted file mode 100644
From commits-noreply at bitbucket.org Sun May 8 17:53:47 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:47 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 565bb86a3522 on
branch 0.6
Message-ID: <20110508155347.9BD002A203D@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43963:fb1993fe0d9b
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/fb1993fe0d9b/
Log: Merge closed head 565bb86a3522 on branch 0.6
From commits-noreply at bitbucket.org Sun May 8 17:53:48 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:48 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 49239e6057da on
branch 0.6.1
Message-ID: <20110508155348.D57DA2A2037@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43964:eb6a50491f1f
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/eb6a50491f1f/
Log: Merge closed head 49239e6057da on branch 0.6.1
From commits-noreply at bitbucket.org Sun May 8 17:53:51 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:51 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 9f70c0dfc643 on
branch pypy-0.7.0-beta
Message-ID: <20110508155351.0AA2136C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43965:f79a28ab084a
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/f79a28ab084a/
Log: Merge closed head 9f70c0dfc643 on branch pypy-0.7.0-beta
From commits-noreply at bitbucket.org Sun May 8 17:53:53 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:53 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 36dbe082a09e on
branch 0.7.x
Message-ID: <20110508155353.2DCA02A203E@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43966:e83e7e49d9c1
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/e83e7e49d9c1/
Log: Merge closed head 36dbe082a09e on branch 0.7.x
From commits-noreply at bitbucket.org Sun May 8 17:53:54 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:54 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head cb9444f10641 on
branch 0.7.0
Message-ID: <20110508155354.9AAEC36C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43967:de644a932841
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/de644a932841/
Log: Merge closed head cb9444f10641 on branch 0.7.0
From commits-noreply at bitbucket.org Sun May 8 17:53:55 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:55 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 4be015f9295a on
branch pypy-0.6.1
Message-ID: <20110508155355.D421436C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43968:8957dbfa1eee
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/8957dbfa1eee/
Log: Merge closed head 4be015f9295a on branch pypy-0.6.1
From commits-noreply at bitbucket.org Sun May 8 17:53:57 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:57 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 81f1d85451f3 on
branch 0.8.x
Message-ID: <20110508155357.34F6F2A2042@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43969:c914e1fe07b6
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/c914e1fe07b6/
Log: Merge closed head 81f1d85451f3 on branch 0.8.x
From commits-noreply at bitbucket.org Sun May 8 17:53:59 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:53:59 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 725851f384a7 on
branch 0.8.0
Message-ID: <20110508155359.CB8A42A2040@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43970:783dbeeb68e7
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/783dbeeb68e7/
Log: Merge closed head 725851f384a7 on branch 0.8.0
From commits-noreply at bitbucket.org Sun May 8 17:54:01 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:01 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 82331b0d5205 on
branch dist-ext-someobject
Message-ID: <20110508155401.3013C2A203B@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43971:e12fbd2accd4
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/e12fbd2accd4/
Log: Merge closed head 82331b0d5205 on branch dist-ext-someobject
From commits-noreply at bitbucket.org Sun May 8 17:54:03 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:03 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head a4a153831588 on
branch 0.9.x
Message-ID: <20110508155403.70CDB36C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43972:ebf5b18429c3
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/ebf5b18429c3/
Log: Merge closed head a4a153831588 on branch 0.9.x
From commits-noreply at bitbucket.org Sun May 8 17:54:04 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:04 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 72f2e4d19c6a on
branch 0.9.0
Message-ID: <20110508155404.A19892A2037@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43973:74849e9ce979
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/74849e9ce979/
Log: Merge closed head 72f2e4d19c6a on branch 0.9.0
From commits-noreply at bitbucket.org Sun May 8 17:54:06 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:06 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head fbb85b5201cd on
branch 0.6.x
Message-ID: <20110508155406.68DD62A203D@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43974:fd108b6de060
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/fd108b6de060/
Log: Merge closed head fbb85b5201cd on branch 0.6.x
From commits-noreply at bitbucket.org Sun May 8 17:54:08 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:08 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 9a33ba52e04c on
branch 0.99.x
Message-ID: <20110508155408.22CF236C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43975:fd99dbfc3f3c
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/fd99dbfc3f3c/
Log: Merge closed head 9a33ba52e04c on branch 0.99.x
From commits-noreply at bitbucket.org Sun May 8 17:54:09 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:09 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head bd4e3cdb7cd4 on
branch 0.99.0
Message-ID: <20110508155409.63A7736C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43976:46b633ca3173
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/46b633ca3173/
Log: Merge closed head bd4e3cdb7cd4 on branch 0.99.0
From commits-noreply at bitbucket.org Sun May 8 17:54:10 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:10 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head f5e89cf13fac on
branch 1.0.x
Message-ID: <20110508155410.82A072A2037@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43977:d5e3c973fdad
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/d5e3c973fdad/
Log: Merge closed head f5e89cf13fac on branch 1.0.x
From commits-noreply at bitbucket.org Sun May 8 17:54:13 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:13 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head cef934e64baf on
branch 1.0.0
Message-ID: <20110508155413.0A32C2A2037@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43978:2a4c71b6b28a
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/2a4c71b6b28a/
Log: Merge closed head cef934e64baf on branch 1.0.0
From commits-noreply at bitbucket.org Sun May 8 17:54:14 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:14 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 0edf0981c9c7 on
branch 1.1.x
Message-ID: <20110508155414.47DEE36C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43979:2d5121923fdb
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/2d5121923fdb/
Log: Merge closed head 0edf0981c9c7 on branch 1.1.x
From commits-noreply at bitbucket.org Sun May 8 17:54:15 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:15 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head cce877990433 on
branch 1.1.0beta
Message-ID: <20110508155415.85C6E2A2037@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43980:f8e50b45a2bb
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/f8e50b45a2bb/
Log: Merge closed head cce877990433 on branch 1.1.0beta
From commits-noreply at bitbucket.org Sun May 8 17:54:17 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:17 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 8ce95515da1a on
branch 1.1.0
Message-ID: <20110508155417.BA20D2A203F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43981:f76ab1b6410b
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/f76ab1b6410b/
Log: Merge closed head 8ce95515da1a on branch 1.1.0
From commits-noreply at bitbucket.org Sun May 8 17:54:19 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:19 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head b4e1c4f296cc on
branch 1.2.x
Message-ID: <20110508155419.1C76036C20F@codespeak.net>
Author: Armin Rigo
Branch: closed-branches
Changeset: r43982:c4efa437c880
Date: 2011-05-08 17:28 +0200
http://bitbucket.org/pypy/pypy/changeset/c4efa437c880/
Log: Merge closed head b4e1c4f296cc on branch 1.2.x
From commits-noreply at bitbucket.org Sun May 8 17:54:20 2011
From: commits-noreply at bitbucket.org (arigo)
Date: Sun, 8 May 2011 17:54:20 +0200 (CEST)
Subject: [pypy-svn] pypy closed-branches: Merge closed head 8056c3c5c711 on
branch 1.2.0
Message-ID: <20110508155420.51F812A2036@codespeak.net>
Author: Armin Rigo