From antocuni at codespeak.net Sun Feb 1 13:43:39 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 1 Feb 2009 13:43:39 +0100 (CET) Subject: [pypy-svn] r61492 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090201124339.54EAA16855E@codespeak.net> Author: antocuni Date: Sun Feb 1 13:43:37 2009 New Revision: 61492 Added: pypy/trunk/lib-python/modified-2.5.2/test/test_urllib2_localnet.py - copied, changed from r61459, pypy/trunk/lib-python/2.5.2/test/test_urllib2_localnet.py Log: make sure that the resources acquired by the thread are really released before going on Copied: pypy/trunk/lib-python/modified-2.5.2/test/test_urllib2_localnet.py (from r61459, pypy/trunk/lib-python/2.5.2/test/test_urllib2_localnet.py) ============================================================================== --- pypy/trunk/lib-python/2.5.2/test/test_urllib2_localnet.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_urllib2_localnet.py Sun Feb 1 13:43:37 2009 @@ -248,6 +248,8 @@ def tearDown(self): self.server.stop() + import gc + gc.collect() def test_proxy_with_bad_password_raises_httperror(self): self._digest_auth_handler.add_password(self.REALM, self.URL, From fijal at codespeak.net Sun Feb 1 23:29:33 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 1 Feb 2009 23:29:33 +0100 (CET) Subject: [pypy-svn] r61493 - pypy/extradoc/talk/wroclaw2009 Message-ID: <20090201222933.656A31684D3@codespeak.net> Author: fijal Date: Sun Feb 1 23:29:27 2009 New Revision: 61493 Modified: pypy/extradoc/talk/wroclaw2009/talk.pdf Log: talk in the version I gave Modified: pypy/extradoc/talk/wroclaw2009/talk.pdf ============================================================================== Binary files. No diff available. From afa at codespeak.net Mon Feb 2 09:22:28 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 2 Feb 2009 09:22:28 +0100 (CET) Subject: [pypy-svn] r61507 - pypy/trunk/pypy/rpython/module Message-ID: <20090202082228.A33F216854D@codespeak.net> Author: afa Date: Mon Feb 2 09:22:27 2009 New Revision: 61507 Modified: pypy/trunk/pypy/rpython/module/ll_os.py Log: untabify Modified: pypy/trunk/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os.py Mon Feb 2 09:22:27 2009 @@ -522,7 +522,7 @@ @registering_if(os, 'setpgrp') def register_os_setpgrp(self): - name = 'setpgrp' + name = 'setpgrp' if sys.platform.startswith('freebsd'): c_func = self.llexternal(name, [rffi.INT, rffi.INT], rffi.INT) def c_func_llimpl(): From arigo at codespeak.net Mon Feb 2 10:38:54 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 2 Feb 2009 10:38:54 +0100 (CET) Subject: [pypy-svn] r61511 - in pypy/trunk/pypy: interpreter rpython/memory/gctransform rpython/memory/test Message-ID: <20090202093854.3A3E616855C@codespeak.net> Author: arigo Date: Mon Feb 2 10:38:52 2009 New Revision: 61511 Modified: pypy/trunk/pypy/interpreter/generator.py pypy/trunk/pypy/rpython/memory/gctransform/framework.py pypy/trunk/pypy/rpython/memory/test/snippet.py Log: Fix. As usual around here, it's a 3-lines fix with a pages-long test... Modified: pypy/trunk/pypy/interpreter/generator.py ============================================================================== --- pypy/trunk/pypy/interpreter/generator.py (original) +++ pypy/trunk/pypy/interpreter/generator.py Mon Feb 2 10:38:52 2009 @@ -124,8 +124,6 @@ """ self.descr_close() -## # it seems there is a bug in the hybrid gc, if we add a __del__ it -## # segfaults. With mark&sweep it works correctly -## def __del__(self): -## if not self.frame.frame_finished_execution: -## self._enqueue_for_destruction(self.space) + def __del__(self): + if not self.frame.frame_finished_execution: + self._enqueue_for_destruction(self.space) Modified: pypy/trunk/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/trunk/pypy/rpython/memory/gctransform/framework.py Mon Feb 2 10:38:52 2009 @@ -87,6 +87,9 @@ mallocop.result is checkop.args[0] and block.exitswitch is checkop.result): continue + rtti = get_rtti(mallocop.args[0].value) + if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): + continue exits = [exit for exit in block.exits if exit.llexitcase] if len(exits) != 1: continue Modified: pypy/trunk/pypy/rpython/memory/test/snippet.py ============================================================================== --- pypy/trunk/pypy/rpython/memory/test/snippet.py (original) +++ pypy/trunk/pypy/rpython/memory/test/snippet.py Mon Feb 2 10:38:52 2009 @@ -125,3 +125,36 @@ print summary print msg py.test.fail(msg) + + + def test_from_objwithfinalizer_to_youngobj(self): + import gc + if self.large_tests_ok: + MAX = 500000 + else: + MAX = 150 + + class B: + count = 0 + class A: + def __del__(self): + self.b.count += 1 + def g(): + b = B() + a = A() + a.b = b + i = 0 + lst = [None] + while i < MAX: + lst[0] = str(i) + i += 1 + return a.b, lst + g._dont_inline_ = True + + def f(): + b, lst = g() + gc.collect() + return str(b.count) + + res = self.run(f) + assert res == '1' From cfbolz at codespeak.net Mon Feb 2 15:45:43 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 2 Feb 2009 15:45:43 +0100 (CET) Subject: [pypy-svn] r61518 - pypy/branch/spy-graphic Message-ID: <20090202144543.6CE87169E17@codespeak.net> Author: cfbolz Date: Mon Feb 2 15:45:41 2009 New Revision: 61518 Added: pypy/branch/spy-graphic/ - copied from r61517, pypy/trunk/ Log: make a branch to experiment with adding graphics support to SPy From antocuni at codespeak.net Mon Feb 2 16:18:46 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 2 Feb 2009 16:18:46 +0100 (CET) Subject: [pypy-svn] r61519 - pypy/trunk/lib-python/modified-2.5.2/test/output Message-ID: <20090202151846.451E5169DF6@codespeak.net> Author: antocuni Date: Mon Feb 2 16:18:45 2009 New Revision: 61519 Added: pypy/trunk/lib-python/modified-2.5.2/test/output/test_cProfile Log: add the exact output for test_cProfile as produced by PyPy. There is no chance to have the exact same representation as CPython Added: pypy/trunk/lib-python/modified-2.5.2/test/output/test_cProfile ============================================================================== --- (empty file) +++ pypy/trunk/lib-python/modified-2.5.2/test/output/test_cProfile Mon Feb 2 16:18:45 2009 @@ -0,0 +1,79 @@ +test_cProfile + 126 function calls (106 primitive calls) in 1.000 CPU seconds + + Ordered by: standard name + + ncalls tottime percall cumtime percall filename:lineno(function) + 1 0.000 0.000 1.000 1.000 :1() + 8 0.064 0.008 0.080 0.010 test_cProfile.py:103(subhelper) + 28 0.028 0.001 0.028 0.001 test_cProfile.py:115(__getattr__) + 1 0.270 0.270 1.000 1.000 test_cProfile.py:30(testfunc) + 23/3 0.150 0.007 0.170 0.057 test_cProfile.py:40(factorial) + 20 0.020 0.001 0.020 0.001 test_cProfile.py:53(mul) + 2 0.040 0.020 0.600 0.300 test_cProfile.py:60(helper) + 4 0.116 0.029 0.120 0.030 test_cProfile.py:78(helper1) + 2 0.000 0.000 0.140 0.070 test_cProfile.py:89(helper2_indirect) + 8 0.312 0.039 0.400 0.050 test_cProfile.py:93(helper2) + 4 0.000 0.000 0.000 0.000 {append} + 1 0.000 0.000 0.000 0.000 {disable} + 12 0.000 0.000 0.012 0.001 {hasattr} + 8 0.000 0.000 0.000 0.000 {range} + 4 0.000 0.000 0.000 0.000 {sys.exc_info} + + + Ordered by: standard name + +Function called... + ncalls tottime cumtime +:1() -> 1 0.270 1.000 test_cProfile.py:30(testfunc) +test_cProfile.py:103(subhelper) -> 16 0.016 0.016 test_cProfile.py:115(__getattr__) + 8 0.000 0.000 {range} +test_cProfile.py:115(__getattr__) -> +test_cProfile.py:30(testfunc) -> 1 0.014 0.130 test_cProfile.py:40(factorial) + 2 0.040 0.600 test_cProfile.py:60(helper) +test_cProfile.py:40(factorial) -> 20/3 0.130 0.147 test_cProfile.py:40(factorial) + 20 0.020 0.020 test_cProfile.py:53(mul) +test_cProfile.py:53(mul) -> +test_cProfile.py:60(helper) -> 4 0.116 0.120 test_cProfile.py:78(helper1) + 2 0.000 0.140 test_cProfile.py:89(helper2_indirect) + 6 0.234 0.300 test_cProfile.py:93(helper2) +test_cProfile.py:78(helper1) -> 4 0.000 0.000 {append} + 4 0.000 0.004 {hasattr} + 4 0.000 0.000 {sys.exc_info} +test_cProfile.py:89(helper2_indirect) -> 2 0.006 0.040 test_cProfile.py:40(factorial) + 2 0.078 0.100 test_cProfile.py:93(helper2) +test_cProfile.py:93(helper2) -> 8 0.064 0.080 test_cProfile.py:103(subhelper) + 8 0.000 0.008 {hasattr} +{append} -> +{disable} -> +{hasattr} -> 12 0.012 0.012 test_cProfile.py:115(__getattr__) +{range} -> +{sys.exc_info} -> + + + Ordered by: standard name + +Function was called by... + ncalls tottime cumtime +:1() <- +test_cProfile.py:103(subhelper) <- 8 0.064 0.080 test_cProfile.py:93(helper2) +test_cProfile.py:115(__getattr__) <- 16 0.016 0.016 test_cProfile.py:103(subhelper) + 12 0.012 0.012 {hasattr} +test_cProfile.py:30(testfunc) <- 1 0.270 1.000 :1() +test_cProfile.py:40(factorial) <- 1 0.014 0.130 test_cProfile.py:30(testfunc) + 20/3 0.130 0.147 test_cProfile.py:40(factorial) + 2 0.006 0.040 test_cProfile.py:89(helper2_indirect) +test_cProfile.py:53(mul) <- 20 0.020 0.020 test_cProfile.py:40(factorial) +test_cProfile.py:60(helper) <- 2 0.040 0.600 test_cProfile.py:30(testfunc) +test_cProfile.py:78(helper1) <- 4 0.116 0.120 test_cProfile.py:60(helper) +test_cProfile.py:89(helper2_indirect) <- 2 0.000 0.140 test_cProfile.py:60(helper) +test_cProfile.py:93(helper2) <- 6 0.234 0.300 test_cProfile.py:60(helper) + 2 0.078 0.100 test_cProfile.py:89(helper2_indirect) +{append} <- 4 0.000 0.000 test_cProfile.py:78(helper1) +{disable} <- +{hasattr} <- 4 0.000 0.004 test_cProfile.py:78(helper1) + 8 0.000 0.008 test_cProfile.py:93(helper2) +{range} <- 8 0.000 0.000 test_cProfile.py:103(subhelper) +{sys.exc_info} <- 4 0.000 0.000 test_cProfile.py:78(helper1) + + From fijal at codespeak.net Mon Feb 2 16:32:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Feb 2009 16:32:58 +0100 (CET) Subject: [pypy-svn] r61520 - pypy/trunk/pypy/module/_codecs/test Message-ID: <20090202153258.9F28D169E13@codespeak.net> Author: fijal Date: Mon Feb 2 16:32:57 2009 New Revision: 61520 Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py Log: oops. Apparently this was testing cpython's encoding instead of ours and cpython 2.4 was broken. Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/test/test_codecs.py Mon Feb 2 16:32:57 2009 @@ -515,6 +515,11 @@ assert codecs.getencoder('utf-16')(x) == ('\xff\xfe1\x002\x003\x00a\x00b\x00c\x00', 6) assert codecs.getdecoder('utf-16')('\xff\xfe1\x002\x003\x00a\x00b\x00c\x00') == (x, 14) + def test_unicode_escape(self): + assert u'\\'.encode('unicode-escape') == '\\\\' + assert '\\\\'.decode('unicode-escape') == u'\\' + + class TestDirect: def test_charmap_encode(self): assert charmap_encode(u'xxx') == ('xxx', 3) @@ -528,6 +533,3 @@ assert unicode_escape_encode(u'abc') == (u'abc'.encode('unicode_escape'), 3) assert unicode_escape_decode('abc') == (u'abc'.decode('unicode_escape'), 3) assert unicode_escape_decode('\\x61\\x62\\x63') == (u'abc', 12) - - assert u'\\'.encode('unicode-escape') == '\\\\' - assert '\\\\'.decode('unicode-escape') == u'\\' From fijal at codespeak.net Mon Feb 2 16:44:46 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Feb 2009 16:44:46 +0100 (CET) Subject: [pypy-svn] r61521 - pypy/trunk/pypy/module/bz2 Message-ID: <20090202154446.309CA169E13@codespeak.net> Author: fijal Date: Mon Feb 2 16:44:44 2009 New Revision: 61521 Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py Log: seems that bz2 has a bit more relaxed rules than normal files (ie 'U' does not mean we cannot use 'a' or 'w') Modified: pypy/trunk/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/trunk/pypy/module/bz2/interp_bz2.py (original) +++ pypy/trunk/pypy/module/bz2/interp_bz2.py Mon Feb 2 16:44:44 2009 @@ -173,6 +173,12 @@ class W_BZ2File(W_File): + def check_mode_ok(self, mode): + if (not mode or mode[0] not in ['r', 'w', 'a', 'U']): + space = self.space + raise OperationError(space.w_ValueError, + space.wrap('invalid mode : "%s"' % mode)) + def direct_bz2__init__(self, w_name, mode='r', buffering=-1, compresslevel=9): self.direct_close() From fijal at codespeak.net Mon Feb 2 16:50:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Feb 2009 16:50:27 +0100 (CET) Subject: [pypy-svn] r61522 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090202155027.DBEC3169E29@codespeak.net> Author: fijal Date: Mon Feb 2 16:50:27 2009 New Revision: 61522 Modified: pypy/trunk/pypy/objspace/std/test/test_ropeobject.py pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py Log: skip a couple of tests for ropes Modified: pypy/trunk/pypy/objspace/std/test/test_ropeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_ropeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_ropeobject.py Mon Feb 2 16:50:27 2009 @@ -80,6 +80,9 @@ def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withrope": True}) + def test_rfind(self): + skip("XXX Fix") + class AppTestPrebuilt(AppTestRopeObject): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withrope": True, Modified: pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py Mon Feb 2 16:50:27 2009 @@ -19,11 +19,17 @@ # strings pass + def test_replace_buffer(self): + skip("XXX fix") + class AppTestRopeUnicode(object): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withropeunicode": True}) + def test_replace_buffer(self): + skip("XXX fix") + class AppTestUnicodeRopeStdOnly(test_unicodeobject.AppTestUnicodeStringStdOnly): def setup_class(cls): @@ -33,3 +39,16 @@ def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withropeunicode": True}) + + def test_replace_buffer(self): + skip("XXX fix") + + def test_replace_with_buffer(self): + skip("XXX fix") + + def test_rfind(self): + skip("XXX fix") + + def test_rsplit(self): + skip("XXX fix") + From fijal at codespeak.net Mon Feb 2 17:04:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Feb 2009 17:04:21 +0100 (CET) Subject: [pypy-svn] r61523 - pypy/trunk/pypy/rlib/test Message-ID: <20090202160421.B2807169E29@codespeak.net> Author: fijal Date: Mon Feb 2 17:04:21 2009 New Revision: 61523 Modified: pypy/trunk/pypy/rlib/test/test_rsocket.py Log: I think this assertion is not always true Modified: pypy/trunk/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rsocket.py (original) +++ pypy/trunk/pypy/rlib/test/test_rsocket.py Mon Feb 2 17:04:21 2009 @@ -157,7 +157,7 @@ lock.acquire() print 'connecting side knows that the connection was accepted too' assert addr.eq(s2.getpeername()) - assert addr2.eq(s2.getsockname()) + #assert addr2.eq(s2.getsockname()) assert addr2.eq(s1.getpeername()) s1.send('?') From fijal at codespeak.net Mon Feb 2 17:08:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 2 Feb 2009 17:08:27 +0100 (CET) Subject: [pypy-svn] r61525 - pypy/trunk/pypy/rlib/test Message-ID: <20090202160827.98539169E29@codespeak.net> Author: fijal Date: Mon Feb 2 17:08:23 2009 New Revision: 61525 Modified: pypy/trunk/pypy/rlib/test/test_rsocket.py Log: a debug print Modified: pypy/trunk/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rsocket.py (original) +++ pypy/trunk/pypy/rlib/test/test_rsocket.py Mon Feb 2 17:08:23 2009 @@ -205,6 +205,7 @@ assert 1 <= count <= 99 buf, addr3 = s1.recvfrom(100) assert buf == 'x'*count + print addr2, addr3 assert addr3.eq(addr2) s1.close() s2.close() From cami at codespeak.net Mon Feb 2 22:43:36 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 2 Feb 2009 22:43:36 +0100 (CET) Subject: [pypy-svn] r61527 - pypy/trunk/pypy/lang/gameboy/debug Message-ID: <20090202214336.1A139169E3C@codespeak.net> Author: cami Date: Mon Feb 2 22:43:35 2009 New Revision: 61527 Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py Log: changing wrong default path for the debugging jar Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py Mon Feb 2 22:43:35 2009 @@ -70,15 +70,15 @@ # ------------------------------------------------------------------------------ -JMARIO_DIR = str(py.magic.autopath().dirpath().dirpath()\ +MARIO_DIR = str(py.magic.autopath().dirpath().dirpath()\ .dirpath().dirpath()\ - .dirpath().dirpath()) + "/jmario" + .dirpath().dirpath()) + "/mario" -JAVA_CLASSPATH =[ JMARIO_DIR+"/build/", - JMARIO_DIR + "/lib/xmlrpc-client-3.1.jar", - JMARIO_DIR + "/lib/xmlrpc-common-3.1.jar", - JMARIO_DIR + "/lib/ws-commons-util-1.0.2.jar", - JMARIO_DIR + "/lib/commons-logging-1.1.jar"]; +JAVA_CLASSPATH =[ MARIO_DIR+"/build/", + MARIO_DIR + "/lib/xmlrpc-client-3.1.jar", + MARIO_DIR + "/lib/xmlrpc-common-3.1.jar", + MARIO_DIR + "/lib/ws-commons-util-1.0.2.jar", + MARIO_DIR + "/lib/commons-logging-1.1.jar"]; def start_java_version(): global filename @@ -95,7 +95,11 @@ # filename + " " os.system(command) - +#try: +# import psyco +# psyco.full() +#except: +# pass # START ======================================================================== parse_file_name() From afa at codespeak.net Tue Feb 3 02:06:09 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 3 Feb 2009 02:06:09 +0100 (CET) Subject: [pypy-svn] r61529 - pypy/trunk/lib-python/modified-2.5.2 Message-ID: <20090203010609.59C48169E13@codespeak.net> Author: afa Date: Tue Feb 3 02:06:08 2009 New Revision: 61529 Added: pypy/trunk/lib-python/modified-2.5.2/filecmp.py - copied, changed from r61434, pypy/trunk/lib-python/2.5.2/filecmp.py Log: Fix test_filecmp on Windows, by closing opened files before the tests try to unlink them. Copied: pypy/trunk/lib-python/modified-2.5.2/filecmp.py (from r61434, pypy/trunk/lib-python/2.5.2/filecmp.py) ============================================================================== --- pypy/trunk/lib-python/2.5.2/filecmp.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/filecmp.py Tue Feb 3 02:06:08 2009 @@ -63,15 +63,22 @@ def _do_cmp(f1, f2): bufsize = BUFSIZE - fp1 = open(f1, 'rb') - fp2 = open(f2, 'rb') - while True: - b1 = fp1.read(bufsize) - b2 = fp2.read(bufsize) - if b1 != b2: - return False - if not b1: - return True + fp1, fp2 = None, None + try: + fp1 = open(f1, 'rb') + fp2 = open(f2, 'rb') + while True: + b1 = fp1.read(bufsize) + b2 = fp2.read(bufsize) + if b1 != b2: + return False + if not b1: + return True + finally: + if fp1: + fp1.close() + if fp2: + fp2.close() # Directory comparison class. # From fijal at codespeak.net Tue Feb 3 11:01:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Feb 2009 11:01:09 +0100 (CET) Subject: [pypy-svn] r61530 - pypy/trunk/pypy Message-ID: <20090203100109.8E082168502@codespeak.net> Author: fijal Date: Tue Feb 3 11:01:07 2009 New Revision: 61530 Modified: pypy/trunk/pypy/conftest.py Log: Last missing part for applevel zipimporter tests Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Tue Feb 3 11:01:07 2009 @@ -149,6 +149,9 @@ def setattr(self, obj, name, value): setattr(obj, name, value) + def getbuiltinmodule(self, name): + return __import__(name) + def translation_test_so_skip_if_appdirect(): if option.runappdirect: py.test.skip("translation test, skipped for appdirect") From fijal at codespeak.net Tue Feb 3 13:48:15 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 3 Feb 2009 13:48:15 +0100 (CET) Subject: [pypy-svn] r61532 - pypy/trunk/pypy/module/thread Message-ID: <20090203124815.8B749169E27@codespeak.net> Author: fijal Date: Tue Feb 3 13:48:13 2009 New Revision: 61532 Modified: pypy/trunk/pypy/module/thread/ll_thread.py Log: I think we always include python include path anyway and this breaks py.test -A Modified: pypy/trunk/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/trunk/pypy/module/thread/ll_thread.py (original) +++ pypy/trunk/pypy/module/thread/ll_thread.py Tue Feb 3 13:48:13 2009 @@ -14,8 +14,6 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem.lloperation import llop from pypy.tool import autopath -from distutils import sysconfig -python_inc = sysconfig.get_python_inc() class error(Exception): pass @@ -23,8 +21,7 @@ eci = ExternalCompilationInfo( includes = ['src/thread.h'], separate_module_sources = [''], - include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c')), - python_inc], + include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c'))], export_symbols = ['RPyThreadGetIdent', 'RPyThreadLockInit', 'RPyThreadAcquireLock', 'RPyThreadReleaseLock', 'RPyThreadYield'] From antocuni at codespeak.net Tue Feb 3 14:45:04 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 3 Feb 2009 14:45:04 +0100 (CET) Subject: [pypy-svn] r61533 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090203134504.2618E169E51@codespeak.net> Author: antocuni Date: Tue Feb 3 14:45:03 2009 New Revision: 61533 Added: pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py - copied, changed from r61532, pypy/trunk/lib-python/2.5.2/test/test_dis.py Log: mark some tests as impl detail, and port one of those to pypy Copied: pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py (from r61532, pypy/trunk/lib-python/2.5.2/test/test_dis.py) ============================================================================== --- pypy/trunk/lib-python/2.5.2/test/test_dis.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py Tue Feb 3 14:45:03 2009 @@ -1,4 +1,5 @@ from test.test_support import verify, verbose, TestFailed, run_unittest +from test.test_support import impl_detail, check_impl_detail import sys import dis import StringIO @@ -11,7 +12,7 @@ print a return 1 -dis_f = """\ +dis_f_cpy = """\ %-4d 0 LOAD_FAST 0 (a) 3 PRINT_ITEM 4 PRINT_NEWLINE @@ -21,6 +22,18 @@ """%(_f.func_code.co_firstlineno + 1, _f.func_code.co_firstlineno + 2) +dis_f_pypy = """\ + %-4d 0 LOAD_FAST 0 (a) + 3 PRINT_ITEM + 4 PRINT_NEWLINE + + %-4d 5 LOAD_CONST 1 (1) + 8 RETURN_VALUE + 9 LOAD_CONST 0 (None) + 12 RETURN_VALUE +"""%(_f.func_code.co_firstlineno + 1, + _f.func_code.co_firstlineno + 2) + def bug708901(): for res in range(1, @@ -120,11 +133,16 @@ self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT) def test_dis(self): - self.do_disassembly_test(_f, dis_f) + if check_impl_detail(pypy=True): + self.do_disassembly_test(_f, dis_f_pypy) + else: + self.do_disassembly_test(_f, dis_f_cpy) + @impl_detail("PyPy compilers produce different opcodes") def test_bug_708901(self): self.do_disassembly_test(bug708901, dis_bug708901) + @impl_detail("see pypy issue 424") def test_bug_1333982(self): # This one is checking bytecodes generated for an `assert` statement, # so fails if the tests are run with -O. Skip this test then. From antocuni at codespeak.net Tue Feb 3 14:53:22 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 3 Feb 2009 14:53:22 +0100 (CET) Subject: [pypy-svn] r61534 - pypy/trunk/lib-python/modified-2.5.2/distutils/tests Message-ID: <20090203135322.581CC169E53@codespeak.net> Author: antocuni Date: Tue Feb 3 14:53:21 2009 New Revision: 61534 Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_install.py Log: this distutils test is clearly impl detail Modified: pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_install.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_install.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/distutils/tests/test_install.py Tue Feb 3 14:53:21 2009 @@ -2,6 +2,7 @@ import os import unittest +from test.test_support import check_impl_detail from distutils.command.install import install from distutils.core import Distribution @@ -38,15 +39,16 @@ expected = os.path.normpath(expected) self.assertEqual(got, expected) - libdir = os.path.join(destination, "lib", "python") - check_path(cmd.install_lib, libdir) - check_path(cmd.install_platlib, libdir) - check_path(cmd.install_purelib, libdir) - check_path(cmd.install_headers, - os.path.join(destination, "include", "python", "foopkg")) - check_path(cmd.install_scripts, os.path.join(destination, "bin")) - check_path(cmd.install_data, destination) + if check_impl_detail(): + libdir = os.path.join(destination, "lib", "python") + check_path(cmd.install_lib, libdir) + check_path(cmd.install_platlib, libdir) + check_path(cmd.install_purelib, libdir) + check_path(cmd.install_headers, + os.path.join(destination, "include", "python", "foopkg")) + check_path(cmd.install_scripts, os.path.join(destination, "bin")) + check_path(cmd.install_data, destination) def test_suite(): return unittest.makeSuite(InstallTestCase) From antocuni at codespeak.net Tue Feb 3 17:35:04 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 3 Feb 2009 17:35:04 +0100 (CET) Subject: [pypy-svn] r61537 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090203163504.5CC9B169E9E@codespeak.net> Author: antocuni Date: Tue Feb 3 17:35:02 2009 New Revision: 61537 Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_generators.py Log: fix some slightly difference in the output Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_generators.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_generators.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_generators.py Tue Feb 3 17:35:02 2009 @@ -1682,7 +1682,7 @@ >>> del g >>> import gc; _ = gc.collect() >>> sys.stderr.getvalue().startswith( -... "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in " +... 'Exception "RuntimeError: generator ignored GeneratorExit" in ' ... ) True >>> sys.stderr = old From antocuni at codespeak.net Tue Feb 3 17:48:03 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 3 Feb 2009 17:48:03 +0100 (CET) Subject: [pypy-svn] r61538 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090203164803.BED9A169E85@codespeak.net> Author: antocuni Date: Tue Feb 3 17:48:01 2009 New Revision: 61538 Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_generators.py Log: make this test passing both on cpython and pypy; some tests still fail on cpython, though :-( Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_generators.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_generators.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_generators.py Tue Feb 3 17:48:01 2009 @@ -1681,10 +1681,8 @@ >>> g.next() >>> del g >>> import gc; _ = gc.collect() ->>> sys.stderr.getvalue().startswith( -... 'Exception "RuntimeError: generator ignored GeneratorExit" in ' -... ) -True +>>> print sys.stderr.getvalue() # doctest: +ELLIPSIS +Exception ...RuntimeError...generator ignored GeneratorExit... >>> sys.stderr = old From antocuni at codespeak.net Wed Feb 4 11:00:53 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 4 Feb 2009 11:00:53 +0100 (CET) Subject: [pypy-svn] r61540 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090204100053.76393168502@codespeak.net> Author: antocuni Date: Wed Feb 4 11:00:50 2009 New Revision: 61540 Added: pypy/trunk/lib-python/modified-2.5.2/test/test_functools.py - copied, changed from r61532, pypy/trunk/lib-python/2.5.2/test/test_functools.py Log: make test_functools passing; for one test, we raise AttributeError instead of TypeError when trying to delete an attribute, but I think it can be considered impl detail. For the other, we just need to add the usual gc.collect() Copied: pypy/trunk/lib-python/modified-2.5.2/test/test_functools.py (from r61532, pypy/trunk/lib-python/2.5.2/test/test_functools.py) ============================================================================== --- pypy/trunk/lib-python/2.5.2/test/test_functools.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_functools.py Wed Feb 4 11:00:50 2009 @@ -121,7 +121,7 @@ p = self.thetype(hex) try: del p.__dict__ - except TypeError: + except (TypeError, AttributeError): pass else: self.fail('partial object allowed __dict__ to be deleted') @@ -131,6 +131,8 @@ p = proxy(f) self.assertEqual(f.func, p.func) f = None + import gc + gc.collect() self.assertRaises(ReferenceError, getattr, p, 'func') def test_with_bound_and_unbound_methods(self): From antocuni at codespeak.net Wed Feb 4 11:18:46 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 4 Feb 2009 11:18:46 +0100 (CET) Subject: [pypy-svn] r61542 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090204101846.633EF169E34@codespeak.net> Author: antocuni Date: Wed Feb 4 11:18:43 2009 New Revision: 61542 Added: pypy/trunk/lib-python/modified-2.5.2/test/test_grammar.py - copied, changed from r61532, pypy/trunk/lib-python/2.5.2/test/test_grammar.py Log: add a couple of check_impl_detail, but the test still fails Copied: pypy/trunk/lib-python/modified-2.5.2/test/test_grammar.py (from r61532, pypy/trunk/lib-python/2.5.2/test/test_grammar.py) ============================================================================== --- pypy/trunk/lib-python/2.5.2/test/test_grammar.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_grammar.py Wed Feb 4 11:18:43 2009 @@ -8,7 +8,7 @@ # regression test, the filterwarnings() call has been added to # regrtest.py. -from test.test_support import TestFailed, verify, vereq, check_syntax +from test.test_support import TestFailed, verify, vereq, check_syntax, check_impl_detail import sys print '1. Parser' @@ -159,13 +159,18 @@ def f5((compound, first), two): pass vereq(f2.func_code.co_varnames, ('one_argument',)) vereq(f3.func_code.co_varnames, ('two', 'arguments')) -if sys.platform.startswith('java'): +if check_impl_detail(jython=True): vereq(f4.func_code.co_varnames, ('two', '(compound, (argument, list))', 'compound', 'argument', 'list',)) vereq(f5.func_code.co_varnames, ('(compound, first)', 'two', 'compound', 'first')) -else: +elif check_impl_detail(pypy=True): + vereq(f4.func_code.co_varnames, + ('two', '.2', 'compound', 'argument', 'list')) + vereq(f5.func_code.co_varnames, + ('.0', 'two', 'compound', 'first')) +elif check_impl_detail(cpython=True): vereq(f4.func_code.co_varnames, ('two', '.1', 'compound', 'argument', 'list')) vereq(f5.func_code.co_varnames, @@ -178,9 +183,11 @@ def v3(a, (b, c), *rest): return a, b, c, rest # ceval unpacks the formal arguments into the first argcount names; # thus, the names nested inside tuples must appear after these names. -if sys.platform.startswith('java'): +if check_impl_detail(jython=True): verify(v3.func_code.co_varnames == ('a', '(b, c)', 'rest', 'b', 'c')) -else: +elif check_impl_detail(pypy=True): + vereq(v3.func_code.co_varnames, ('a', '.2', 'rest', 'b', 'c')) +elif check_impl_detail(cpython=True): vereq(v3.func_code.co_varnames, ('a', '.1', 'rest', 'b', 'c')) verify(v3(1, (2, 3), 4) == (1, 2, 3, (4,))) def d01(a=1): pass From fijal at codespeak.net Wed Feb 4 11:19:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Feb 2009 11:19:48 +0100 (CET) Subject: [pypy-svn] r61543 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090204101948.06CF4169E34@codespeak.net> Author: fijal Date: Wed Feb 4 11:19:48 2009 New Revision: 61543 Modified: pypy/trunk/pypy/objspace/std/test/test_proxy_usercreated.py Log: no way this test can run as appdirect Modified: pypy/trunk/pypy/objspace/std/test/test_proxy_usercreated.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_proxy_usercreated.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_proxy_usercreated.py Wed Feb 4 11:19:48 2009 @@ -1,9 +1,11 @@ +import py from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable from pypy.objspace.std.test.test_proxy_internals import AppProxy from pypy.interpreter.typedef import TypeDef from pypy.interpreter.gateway import interp2app from pypy.objspace.std.transparent import register_proxyable +from pypy.conftest import option class W_Wrapped(Wrappable): def new(space, w_type): @@ -21,6 +23,8 @@ class AppTestProxyNewtype(AppProxy): def setup_class(cls): + if option.runappdirect: + py.test.skip("Impossible to run on appdirect") AppProxy.setup_class.im_func(cls) cls.w_wrapped = cls.space.wrap(W_Wrapped()) register_proxyable(cls.space, W_Wrapped) From afa at codespeak.net Wed Feb 4 11:33:31 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 4 Feb 2009 11:33:31 +0100 (CET) Subject: [pypy-svn] r61544 - pypy/trunk/pypy/lib/app_test/ctypes_tests Message-ID: <20090204103331.89BF0169EC1@codespeak.net> Author: afa Date: Wed Feb 4 11:33:30 2009 New Revision: 61544 Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/_ctypes_test.c pypy/trunk/pypy/lib/app_test/ctypes_tests/conftest.py Log: Use out platform package to compile the _ctypes_test shared library Tests in ctypes_test begin to pass on Windows Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/_ctypes_test.c ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/_ctypes_test.c (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/_ctypes_test.c Wed Feb 4 11:33:30 2009 @@ -1,8 +1,9 @@ -#ifdef MS_WIN32 +#if defined(_MSC_VER) || defined(__CYGWIN__) #include +#define MS_WIN32 #endif -#if defined(MS_WIN32) || defined(__CYGWIN__) +#if defined(MS_WIN32) #define EXPORT(x) __declspec(dllexport) x #else #define EXPORT(x) x Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/conftest.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/conftest.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/conftest.py Wed Feb 4 11:33:30 2009 @@ -1,39 +1,19 @@ import py -import os, sys - +import sys def compile_so_file(): - from distutils.dist import Distribution - from distutils.extension import Extension - from distutils.ccompiler import get_default_compiler + from pypy.translator.platform import platform + from pypy.translator.tool.cbuild import ExternalCompilationInfo udir = py.test.ensuretemp('_ctypes_test') cfile = py.magic.autopath().dirpath().join("_ctypes_test.c") - saved_environ = os.environ.items() - olddir = udir.chdir() - try: - attrs = { - 'name': "_ctypes_test", - 'ext_modules': [ - Extension("_ctypes_test", [str(cfile)]), - ], - 'script_name': 'setup.py', - 'script_args': ['-q', 'build_ext', '--inplace'], - } - dist = Distribution(attrs) - if not dist.parse_command_line(): - raise ValueError, "distutils cmdline parse error" - dist.run_commands() - finally: - olddir.chdir() - for key, value in saved_environ: - if os.environ.get(key) != value: - os.environ[key] = value if sys.platform == 'win32': - so_ext = '.dll' + libraries = ['oleaut32'] else: - so_ext = '.so' - return udir.join('_ctypes_test' + so_ext) + libraries = [] + eci = ExternalCompilationInfo(libraries=libraries) + return platform.compile([cfile], eci, str(udir.join('_ctypes_test')), + standalone=False) sofile = compile_so_file() From afa at codespeak.net Wed Feb 4 12:53:33 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 4 Feb 2009 12:53:33 +0100 (CET) Subject: [pypy-svn] r61545 - pypy/trunk/pypy/lib/app_test/ctypes_tests Message-ID: <20090204115333.6857E1684D6@codespeak.net> Author: afa Date: Wed Feb 4 12:53:31 2009 New Revision: 61545 Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_callbacks.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_cfuncs.py Log: Let these win32-specific tests pass Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_callbacks.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_callbacks.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_callbacks.py Wed Feb 4 12:53:31 2009 @@ -103,7 +103,7 @@ except NameError: pass else: - class StdcallCallbacks(Callbacks): + class TestStdcallCallbacks(TestCallbacks): functype = WINFUNCTYPE ################################################################ Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_cfuncs.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_cfuncs.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_cfuncs.py Wed Feb 4 12:53:31 2009 @@ -195,6 +195,6 @@ setattr(self, name, func) return func - class stdcallCFunctions(CFunctions): - _dll = stdcall_dll(_ctypes_test.__file__) - pass + class TestStdcallCFunctions(TestCFunctions): + def setup_class(cls): + cls._dll = stdcall_dll(_ctypes_test) From afa at codespeak.net Wed Feb 4 13:43:10 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 4 Feb 2009 13:43:10 +0100 (CET) Subject: [pypy-svn] r61546 - in pypy/trunk/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20090204124310.91A01169E34@codespeak.net> Author: afa Date: Wed Feb 4 13:43:08 2009 New Revision: 61546 Modified: pypy/trunk/pypy/lib/_ctypes/structure.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_structures.py Log: Don't smash the __init__ method of classes derived from ctypes.Structure This new test used to fail when run with pypy-c. Modified: pypy/trunk/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/structure.py (original) +++ pypy/trunk/pypy/lib/_ctypes/structure.py Wed Feb 4 13:43:08 2009 @@ -111,22 +111,6 @@ typedict.get('_anonymous_', None)) _set_shape(res, rawfields) - def __init__(self, *args, **kwds): - if not hasattr(self, '_ffistruct'): - raise TypeError("Cannot instantiate structure, has no _fields_") - self.__dict__['_buffer'] = self._ffistruct(autofree=True) - if len(args) > len(self._names): - raise TypeError("too many arguments") - for name, arg in zip(self._names, args): - if name in kwds: - raise TypeError("duplicate value for argument %r" % ( - name,)) - self.__setattr__(name, arg) - for name, arg in kwds.items(): - self.__setattr__(name, arg) - res.__init__ = __init__ - - return res __getattr__ = struct_getattr @@ -168,6 +152,24 @@ class Structure(_CData): __metaclass__ = StructureMeta + def __new__(cls, *args, **kwds): + if not hasattr(cls, '_ffistruct'): + raise TypeError("Cannot instantiate structure, has no _fields_") + self = super(_CData, cls).__new__(cls, *args, **kwds) + self.__dict__['_buffer'] = self._ffistruct(autofree=True) + return self + + def __init__(self, *args, **kwds): + if len(args) > len(self._names): + raise TypeError("too many arguments") + for name, arg in zip(self._names, args): + if name in kwds: + raise TypeError("duplicate value for argument %r" % ( + name,)) + self.__setattr__(name, arg) + for name, arg in kwds.items(): + self.__setattr__(name, arg) + def _subarray(self, fieldtype, name): """Return a _rawffi array of length 1 whose address is the same as the address of the field 'name' of self.""" Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_structures.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_structures.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_structures.py Wed Feb 4 13:43:08 2009 @@ -371,6 +371,19 @@ assert p.age == 6 assert p.income == 5 + def test___init__(self): + class Person(Structure): + _fields_ = (("name", c_char*10), + ("age", c_int)) + + def __init__(self, name, surname, age): + self.name = name + ' ' + surname + self.age = age + + p = Person("John", "Doe", 25) + assert p.name == "John Doe" + assert p.age == 25 + class TestPointerMember(BaseCTypesTestChecker): From afa at codespeak.net Wed Feb 4 13:57:54 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 4 Feb 2009 13:57:54 +0100 (CET) Subject: [pypy-svn] r61547 - pypy/trunk/pypy/translator/platform Message-ID: <20090204125754.15A281684C7@codespeak.net> Author: afa Date: Wed Feb 4 13:57:53 2009 New Revision: 61547 Modified: pypy/trunk/pypy/translator/platform/windows.py Log: Fix platform.compile on Windows when run with pypy-c. Modified: pypy/trunk/pypy/translator/platform/windows.py ============================================================================== --- pypy/trunk/pypy/translator/platform/windows.py (original) +++ pypy/trunk/pypy/translator/platform/windows.py Wed Feb 4 13:57:53 2009 @@ -101,7 +101,11 @@ # The following symbol is used in c/src/stack.h self.cflags.append('/DMAX_STACK_SIZE=%d' % (stack_size - 1024)) - self.add_cpython_dirs = True + if hasattr(sys, 'exec_prefix'): + self.add_cpython_dirs = True + else: + # We are certainly running pypy-c + self.add_cpython_dirs = False def _preprocess_dirs(self, include_dirs): if self.add_cpython_dirs: From fijal at codespeak.net Wed Feb 4 14:59:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Feb 2009 14:59:56 +0100 (CET) Subject: [pypy-svn] r61548 - in pypy/trunk/pypy/interpreter: astcompiler/test pyparser Message-ID: <20090204135956.EA12F1684E1@codespeak.net> Author: fijal Date: Wed Feb 4 14:59:54 2009 New Revision: 61548 Modified: pypy/trunk/pypy/interpreter/astcompiler/test/test_compiler.py pypy/trunk/pypy/interpreter/pyparser/astbuilder.py Log: a test and a fix, hairy... Modified: pypy/trunk/pypy/interpreter/astcompiler/test/test_compiler.py ============================================================================== --- pypy/trunk/pypy/interpreter/astcompiler/test/test_compiler.py (original) +++ pypy/trunk/pypy/interpreter/astcompiler/test/test_compiler.py Wed Feb 4 14:59:54 2009 @@ -681,4 +681,10 @@ """ py.test.raises(SyntaxError, self.simple_test, source, None, None) - + def test_unpack_singletuple(self): + source = """if 1: + l = [] + for x, in [(1,), (2,)]: + l.append(x) + """ + self.simple_test(source, 'l', [1, 2]) Modified: pypy/trunk/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/trunk/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/trunk/pypy/interpreter/pyparser/astbuilder.py Wed Feb 4 14:59:54 2009 @@ -727,7 +727,7 @@ def build_exprlist(builder, nb): """exprlist: expr (',' expr)* [',']""" atoms = get_atoms(builder, nb) - if len(atoms) <= 2: + if len(atoms) < 2: builder.push(atoms[0]) else: items = [atoms[index] for index in range(0, len(atoms), 2)] From arigo at codespeak.net Wed Feb 4 15:25:46 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 4 Feb 2009 15:25:46 +0100 (CET) Subject: [pypy-svn] r61549 - pypy/trunk/pypy/interpreter/test Message-ID: <20090204142546.B9881169E0E@codespeak.net> Author: arigo Date: Wed Feb 4 15:25:44 2009 New Revision: 61549 Modified: pypy/trunk/pypy/interpreter/test/test_generator.py Log: This test was fixed by r61511. Modified: pypy/trunk/pypy/interpreter/test/test_generator.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_generator.py (original) +++ pypy/trunk/pypy/interpreter/test/test_generator.py Wed Feb 4 15:25:44 2009 @@ -165,7 +165,6 @@ raises(RuntimeError, g.close) def test_close_on_collect(self): - skip("uncomment the __del__ in generator.py, but it causes a segfault") ## we need to exec it, else it won't run on python2.4 exec """ def f(): From fijal at codespeak.net Wed Feb 4 17:06:31 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 4 Feb 2009 17:06:31 +0100 (CET) Subject: [pypy-svn] r61550 - pypy/trunk/pypy/module/thread Message-ID: <20090204160631.A3ED9169ECD@codespeak.net> Author: fijal Date: Wed Feb 4 17:06:29 2009 New Revision: 61550 Modified: pypy/trunk/pypy/module/thread/app_thread.py Log: a trivial fix Modified: pypy/trunk/pypy/module/thread/app_thread.py ============================================================================== --- pypy/trunk/pypy/module/thread/app_thread.py (original) +++ pypy/trunk/pypy/module/thread/app_thread.py Wed Feb 4 17:06:29 2009 @@ -7,4 +7,6 @@ raise SystemExit def stack_size(size=0): + if size == 0: + return 0 raise error("not implemented") From cami at codespeak.net Wed Feb 4 22:33:31 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 4 Feb 2009 22:33:31 +0100 (CET) Subject: [pypy-svn] r61552 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090204213331.3456C168557@codespeak.net> Author: cami Date: Wed Feb 4 22:33:28 2009 New Revision: 61552 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Log: added switch for using RSDL or not Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Wed Feb 4 22:33:28 2009 @@ -7,8 +7,10 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants -from pypy.rlib.rsdl import RSDL, RSDL_helper -from pypy.rpython.lltypesystem import lltype, rffi +use_rsdl = False +if use_rsdl: + from pypy.rlib.rsdl import RSDL, RSDL_helper + from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.objectmodel import specialize import time @@ -19,7 +21,8 @@ def __init__(self): GameBoy.__init__(self) self.is_running = False - self.init_sdl() + if use_rsdl: + self.init_sdl() def init_sdl(self): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 @@ -45,24 +48,31 @@ def emulate_cycle(self): self.handle_events() self.emulate(constants.GAMEBOY_CLOCK >> 2) - RSDL.Delay(1) + if use_rsdl: + RSDL.Delay(1) def handle_execution_error(self, error): - lltype.free(self.event, flavor='raw') - RSDL.Quit() + if use_rsdl: + lltype.free(self.event, flavor='raw') + RSDL.Quit() def handle_events(self): - self.poll_event() - if self.check_for_escape(): - self.is_running = False - self.joypad_driver.update(self.event) + if use_rsdl: + self.poll_event() + if self.check_for_escape(): + self.is_running = False + self.joypad_driver.update(self.event) def poll_event(self): - ok = rffi.cast(lltype.Signed, RSDL.PollEvent(self.event)) - return ok > 0 + if use_rsdl: + ok = rffi.cast(lltype.Signed, RSDL.PollEvent(self.event)) + return ok > 0 + else: + return True def check_for_escape(self): + if not use_rsdl: return False c_type = rffi.getintfield(self.event, 'c_type') if c_type == RSDL.KEYDOWN: p = rffi.cast(RSDL.KeyboardEventPtr, self.event) @@ -77,18 +87,17 @@ COLOR_MAP = [0xFFFFFF, 0xCCCCCC, 0x666666, 0x000000] - def __init__(self, use_rsdl=False): + def __init__(self): VideoDriver.__init__(self) - self.use_rsdl = use_rsdl self.create_screen() self.map = [] def create_screen(self): - if self.use_rsdl: + if use_rsdl: self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def update_display(self): - if self.use_rsdl: + if use_rsdl: RSDL.LockSurface(self.screen) self.draw_pixels() RSDL.UnlockSurface(self.screen) @@ -101,7 +110,7 @@ for y in range(self.height): str += "\n" for x in range(self.width): - color = COLOR_MAP[self.get_pixel_color(x, y)] + color = VideoDriverImplementation.COLOR_MAP[self.get_pixel_color(x, y)] RSDL_helper.set_pixel(self.screen, x, y, color) def draw_ascii_pixels(self): @@ -136,6 +145,7 @@ self.last_key = 0 def update(self, event): + if not use_rsdl: return # fetch the event from sdl type = rffi.getintfield(event, 'c_type') if type == RSDL.KEYDOWN: @@ -144,11 +154,11 @@ elif type == RSDL.KEYUP: self.create_called_key(event) self.on_key_up() - pass def create_called_key(self, event): - p = rffi.cast(RSDL.KeyboardEventPtr, event) - self.last_key = rffi.getintfield(p.c_keysym, 'c_sym') + if use_rsdl: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + self.last_key = rffi.getintfield(p.c_keysym, 'c_sym') def on_key_down(self): self.toggleButton(self.get_button_handler(self.last_key), True) @@ -161,6 +171,7 @@ pressButtonFunction(self, enabled) def get_button_handler(self, key): + if not use_rsdl: return None if key == RSDL.K_UP: return JoypadDriver.button_up elif key == RSDL.K_RIGHT: From antocuni at codespeak.net Thu Feb 5 10:35:50 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 5 Feb 2009 10:35:50 +0100 (CET) Subject: [pypy-svn] r61555 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090205093550.2372D169EE3@codespeak.net> Author: antocuni Date: Thu Feb 5 10:35:49 2009 New Revision: 61555 Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_functools.py Log: make test_functools passing Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_functools.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_functools.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_functools.py Thu Feb 5 10:35:49 2009 @@ -161,7 +161,8 @@ updated=functools.WRAPPER_UPDATES): # Check attributes were assigned for name in assigned: - self.failUnless(getattr(wrapper, name) is getattr(wrapped, name)) + # the original cpython test compared with 'is', but it's clearly an impl detail + self.failUnless(getattr(wrapper, name) == getattr(wrapped, name)) # Check attributes were updated for name in updated: wrapper_attr = getattr(wrapper, name) @@ -218,7 +219,7 @@ pass functools.update_wrapper(wrapper, max) self.assertEqual(wrapper.__name__, 'max') - self.assert_(wrapper.__doc__.startswith('max(')) + self.assert_(wrapper.__doc__ == max.__doc__) class TestWraps(TestUpdateWrapper): From afa at codespeak.net Thu Feb 5 12:51:43 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 5 Feb 2009 12:51:43 +0100 (CET) Subject: [pypy-svn] r61556 - pypy/trunk/pypy/rpython/lltypesystem/test Message-ID: <20090205115143.B7B9E168503@codespeak.net> Author: afa Date: Thu Feb 5 12:51:41 2009 New Revision: 61556 Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Log: Fix the test by replacing the plain malloc() call with OP_RAW_MALLOC. Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Thu Feb 5 12:51:41 2009 @@ -71,19 +71,18 @@ assert xf() == 3 def test_string_reverse(self): - # XXX This test crashes with a debug build - # (when python is built WITH_PYMALLOC and PYMALLOC_DEBUG): - # lltype.free calls OP_RAW_FREE() == PyObject_Free(), - # but the buffer comes from a malloc() - if sys.platform == 'win32' and 'python_d' in sys.executable: - py.test.skip("Crash with a debug build") c_source = py.code.Source(""" #include + #include + #include char *f(char* arg) { char *ret; - ret = (char*)malloc(strlen(arg) + 1); + /* lltype.free uses OP_RAW_FREE, we must allocate + * with the matching function + */ + OP_RAW_MALLOC(strlen(arg) + 1, ret, char*) strcpy(ret, arg); return ret; } From afa at codespeak.net Thu Feb 5 15:07:07 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 5 Feb 2009 15:07:07 +0100 (CET) Subject: [pypy-svn] r61560 - pypy/trunk/pypy/rpython/lltypesystem/test Message-ID: <20090205140707.6708E168511@codespeak.net> Author: afa Date: Thu Feb 5 15:07:06 2009 New Revision: 61560 Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Log: It is necessary to declare a function when its return value is a pointer, for platforms where sizeof(void*) > sizeof(int) Otherwise the returned value is truncated to an int and boom. Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Thu Feb 5 15:07:06 2009 @@ -75,7 +75,7 @@ #include #include #include - + char *f(char* arg) { char *ret; @@ -87,7 +87,8 @@ return ret; } """) - eci = ExternalCompilationInfo(separate_module_sources=[c_source]) + eci = ExternalCompilationInfo(separate_module_sources=[c_source], + post_include_bits=['char *f(char*);']) z = llexternal('f', [CCHARP], CCHARP, compilation_info=eci) def f(): From afa at codespeak.net Thu Feb 5 17:47:35 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 5 Feb 2009 17:47:35 +0100 (CET) Subject: [pypy-svn] r61567 - in pypy/trunk/pypy: rpython/lltypesystem translator/c Message-ID: <20090205164735.91A70168558@codespeak.net> Author: afa Date: Thu Feb 5 17:47:33 2009 New Revision: 61567 Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py pypy/trunk/pypy/rpython/lltypesystem/rffi.py pypy/trunk/pypy/translator/c/primitive.py Log: Store runicode strings as arrays of wchar_t Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Thu Feb 5 17:47:33 2009 @@ -41,7 +41,7 @@ rffi.LONGLONG: ctypes.c_longlong, rffi.ULONGLONG: ctypes.c_ulonglong, rffi.SIZE_T: ctypes.c_size_t, - lltype.UniChar: ctypes.c_uint, + lltype.UniChar: ctypes.c_wchar, }) def build_ctypes_struct(S, delayed_builders, max_n=None): Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rffi.py Thu Feb 5 17:47:33 2009 @@ -308,7 +308,7 @@ TYPES.append(name) TYPES += ['signed char', 'unsigned char', 'long long', 'unsigned long long', - 'size_t', 'time_t'] + 'size_t', 'time_t', 'wchar_t'] if os.name != 'nt': TYPES.append('mode_t') TYPES.append('pid_t') @@ -352,6 +352,7 @@ # ULONG r_ulong # LONGLONG r_longlong # ULONGLONG r_ulonglong +# WCHAR_T r_wchar_t # SIZE_T r_size_t # TIME_T r_time_t # -------------------------------------------------------------------- @@ -687,7 +688,7 @@ if tp is lltype.Char: return 1 if tp is lltype.UniChar: - return 4 + return WCHAR_T._type.BITS/8 if tp is lltype.Float: return 8 assert isinstance(tp, lltype.Number) Modified: pypy/trunk/pypy/translator/c/primitive.py ============================================================================== --- pypy/trunk/pypy/translator/c/primitive.py (original) +++ pypy/trunk/pypy/translator/c/primitive.py Thu Feb 5 17:47:33 2009 @@ -152,7 +152,7 @@ Float: 'double @', SingleFloat: 'float @', Char: 'char @', - UniChar: 'unsigned int @', + UniChar: 'wchar_t @', Bool: 'bool_t @', Void: 'void @', Address: 'void* @', From afa at codespeak.net Fri Feb 6 11:28:37 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Feb 2009 11:28:37 +0100 (CET) Subject: [pypy-svn] r61571 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090206102837.1E563169F4A@codespeak.net> Author: afa Date: Fri Feb 6 11:28:35 2009 New Revision: 61571 Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Log: When extracting data from structs, ctypes automatically converts arrays of c_wchar into unicode strings. Use another integer type instead, with the same size. Modified: pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/ll2ctypes.py Fri Feb 6 11:28:35 2009 @@ -41,9 +41,16 @@ rffi.LONGLONG: ctypes.c_longlong, rffi.ULONGLONG: ctypes.c_ulonglong, rffi.SIZE_T: ctypes.c_size_t, - lltype.UniChar: ctypes.c_wchar, }) + # for unicode strings, do not use ctypes.c_wchar because ctypes + # automatically converts arrays into unicode strings. + # Pick the unsigned int that has the same size. + if ctypes.sizeof(ctypes.c_wchar) == ctypes.sizeof(ctypes.c_uint16): + _ctypes_cache[lltype.UniChar] = ctypes.c_uint16 + else: + _ctypes_cache[lltype.UniChar] = ctypes.c_uint32 + def build_ctypes_struct(S, delayed_builders, max_n=None): def builder(): # called a bit later to fill in _fields_ From afa at codespeak.net Fri Feb 6 15:51:02 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Feb 2009 15:51:02 +0100 (CET) Subject: [pypy-svn] r61582 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090206145102.9513A169FBE@codespeak.net> Author: afa Date: Fri Feb 6 15:51:02 2009 New Revision: 61582 Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py Log: Fix rffi for platforms where wchar_t is 'typedef int'. Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rffi.py Fri Feb 6 15:51:02 2009 @@ -688,7 +688,7 @@ if tp is lltype.Char: return 1 if tp is lltype.UniChar: - return WCHAR_T._type.BITS/8 + return r_wchar_t.BITS/8 if tp is lltype.Float: return 8 assert isinstance(tp, lltype.Number) From afa at codespeak.net Fri Feb 6 22:22:52 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Feb 2009 22:22:52 +0100 (CET) Subject: [pypy-svn] r61596 - pypy/trunk/pypy/module/posix/test Message-ID: <20090206212252.B776F16A010@codespeak.net> Author: afa Date: Fri Feb 6 22:22:52 2009 New Revision: 61596 Modified: pypy/trunk/pypy/module/posix/test/test_posix2.py Log: All major platforms have os.popen Modified: pypy/trunk/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/trunk/pypy/module/posix/test/test_posix2.py (original) +++ pypy/trunk/pypy/module/posix/test/test_posix2.py Fri Feb 6 22:22:52 2009 @@ -262,12 +262,11 @@ os.unlink("onefile") pass # <- please, inspect.getsource(), don't crash - if hasattr(__import__(os.name), 'popen'): - def test_popen(self): - os = self.posix - for i in range(5): - stream = os.popen('echo 1') - assert stream.read() == '1\n' + def test_popen(self): + os = self.posix + for i in range(5): + stream = os.popen('echo 1') + assert stream.read() == '1\n' if hasattr(__import__(os.name), '_getfullpathname'): def test__getfullpathname(self): From afa at codespeak.net Fri Feb 6 22:27:54 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Feb 2009 22:27:54 +0100 (CET) Subject: [pypy-svn] r61597 - pypy/trunk/pypy/lib Message-ID: <20090206212754.BFD0D16A035@codespeak.net> Author: afa Date: Fri Feb 6 22:27:54 2009 New Revision: 61597 Modified: pypy/trunk/pypy/lib/dbm.py Log: raises ImportError when the dbm module cannot find a libdb.so to load. Modified: pypy/trunk/pypy/lib/dbm.py ============================================================================== --- pypy/trunk/pypy/lib/dbm.py (original) +++ pypy/trunk/pypy/lib/dbm.py Fri Feb 6 22:27:54 2009 @@ -153,7 +153,7 @@ # XXX this is hopeless... libpath = ctypes.util.find_library('db-4.5') if not libpath: - raise Exception("Cannot find dbm library") + raise ImportError("Cannot find dbm library") lib = CDLL(libpath) # Linux _platform = 'bdb' else: From afa at codespeak.net Fri Feb 6 22:30:47 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Feb 2009 22:30:47 +0100 (CET) Subject: [pypy-svn] r61598 - pypy/trunk/pypy/translator/c Message-ID: <20090206213047.0BD3416A04D@codespeak.net> Author: afa Date: Fri Feb 6 22:30:47 2009 New Revision: 61598 Modified: pypy/trunk/pypy/translator/c/database.py Log: Remove unused import Modified: pypy/trunk/pypy/translator/c/database.py ============================================================================== --- pypy/trunk/pypy/translator/c/database.py (original) +++ pypy/trunk/pypy/translator/c/database.py Fri Feb 6 22:30:47 2009 @@ -3,7 +3,7 @@ Struct, Array, FuncType, PyObject, Void, \ ContainerType, OpaqueType, FixedSizeArray, _uninitialized from pypy.rpython.lltypesystem import lltype -from pypy.rpython.lltypesystem.llmemory import Address, WeakRef, _WeakRefType +from pypy.rpython.lltypesystem.llmemory import WeakRef, _WeakRefType from pypy.rpython.lltypesystem.rffi import CConstant from pypy.tool.sourcetools import valid_identifier from pypy.translator.c.primitive import PrimitiveName, PrimitiveType From afa at codespeak.net Fri Feb 6 23:00:02 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Feb 2009 23:00:02 +0100 (CET) Subject: [pypy-svn] r61599 - pypy/trunk/pypy/module/_codecs/test Message-ID: <20090206220002.5144B16A032@codespeak.net> Author: afa Date: Fri Feb 6 23:00:00 2009 New Revision: 61599 Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py Log: Let the _codecs tests pass when python is built in ucs2 mode. Also remove a duplicate test. Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/test/test_codecs.py Fri Feb 6 23:00:00 2009 @@ -17,7 +17,7 @@ import sys oldmaxunicode = sys.maxunicode if sys.maxunicode <= 0xffff: - sys.maxunicode = 0xffffffff + return # this test cannot run on UCS2 builds u = u'\U00010001\U00020002\U00030003\U00040004\U00050005' for encoding in ('utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', 'raw_unicode_escape', @@ -474,6 +474,7 @@ def test_unicode_internal(self): import codecs + import sys try: '\x00'.decode('unicode-internal') except UnicodeDecodeError: @@ -482,19 +483,27 @@ raise Exception("DID NOT RAISE") res = "\x00\x00\x00\x00\x00".decode("unicode-internal", "replace") - assert res == u"\u0000\ufffd" + if sys.maxunicode > 65535: + assert res == u"\u0000\ufffd" # UCS4 build + else: + assert res == u"\x00\x00\ufffd" # UCS2 build + + res = "\x00\x00\x00\x00\x00".decode("unicode-internal", "ignore") + if sys.maxunicode > 65535: + assert res == u"\u0000" # UCS4 build + else: + assert res == u"\x00\x00" # UCS2 build + def handler_unicodeinternal(exc): if not isinstance(exc, UnicodeDecodeError): raise TypeError("don't know how to handle %r" % exc) return (u"\x01", 1) - - res = "\x00\x00\x00\x00\x00".decode("unicode-internal", "ignore") - assert res == u"\u0000" - res = "\x00\x00\x00\x00\x00".decode("unicode-internal", "replace") - assert res == u"\u0000\ufffd" codecs.register_error("test.hui", handler_unicodeinternal) res = "\x00\x00\x00\x00\x00".decode("unicode-internal", "test.hui") - assert res == u"\u0000\u0001\u0000" + if sys.maxunicode > 65535: + assert res == u"\u0000\u0001\u0000" # UCS4 build + else: + assert res == u"\x00\x00\x01\x00\x00" # UCS2 build def test_charmap_encode(self): assert 'xxx'.encode('charmap') == 'xxx' From afa at codespeak.net Fri Feb 6 23:37:19 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 6 Feb 2009 23:37:19 +0100 (CET) Subject: [pypy-svn] r61600 - in pypy/trunk/pypy: module/_codecs module/_codecs/test rlib Message-ID: <20090206223719.35A7816A026@codespeak.net> Author: afa Date: Fri Feb 6 23:37:18 2009 New Revision: 61600 Modified: pypy/trunk/pypy/module/_codecs/__init__.py pypy/trunk/pypy/module/_codecs/interp_codecs.py pypy/trunk/pypy/module/_codecs/test/test_codecs.py pypy/trunk/pypy/rlib/runicode.py Log: Provide an approximation of the mbcs codec, almost correct on a Western installation of Windows (cp1252). I do have a working complete implementation based on WideCharToMultiByte, but it needs a lot of missing functions from rffi: get_nonmoving_unicodebuffer, unicode_from_buffer &co that I don't want to submit just before the sprint :-) Modified: pypy/trunk/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/__init__.py (original) +++ pypy/trunk/pypy/module/_codecs/__init__.py Fri Feb 6 23:37:18 2009 @@ -1,5 +1,6 @@ from pypy.interpreter.mixedmodule import MixedModule - +from pypy.rlib import runicode + class Module(MixedModule): appleveldefs = { '__doc__' : 'app_codecs.__doc__', @@ -45,6 +46,10 @@ 'readbuffer_encode': 'interp_codecs.buffer_encode', } + if hasattr(runicode, 'str_decode_mbcs'): + interpleveldefs['mbcs_encode'] = 'interp_codecs.mbcs_encode' + interpleveldefs['mbcs_decode'] = 'interp_codecs.mbcs_decode' + def setup_after_space_initialization(self): "NOT_RPYTHON" self.space.appexec([], """(): Modified: pypy/trunk/pypy/module/_codecs/interp_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/interp_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/interp_codecs.py Fri Feb 6 23:37:18 2009 @@ -247,6 +247,9 @@ ]: make_decoder_wrapper(decoders) +if hasattr(runicode, 'str_decode_mbcs'): + make_encoder_wrapper('mbcs_encode') + make_decoder_wrapper('mbcs_decode') def utf_16_ex_decode(space, data, errors='strict', byteorder=0, w_final=False): """None Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/test/test_codecs.py Fri Feb 6 23:37:18 2009 @@ -528,6 +528,15 @@ assert u'\\'.encode('unicode-escape') == '\\\\' assert '\\\\'.decode('unicode-escape') == u'\\' + def test_mbcs(self): + import sys + if sys.platform != 'win32': + return + assert u'test'.encode('mbcs') == 'test' + assert u'caf\xe9'.encode('mbcs') == 'caf\xe9' + assert u'\u040a'.encode('mbcs') == '?' # some cyrillic letter + assert 'cafx\e9'.decode('mbcs') == u'cafx\e9' + class TestDirect: def test_charmap_encode(self): Modified: pypy/trunk/pypy/rlib/runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/runicode.py (original) +++ pypy/trunk/pypy/rlib/runicode.py Fri Feb 6 23:37:18 2009 @@ -451,3 +451,18 @@ def unicode_encode_utf_16_le(s, size, errors, errorhandler=None): return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "little") + + +if sys.platform == 'win32': + def str_decode_mbcs(s, size, errors, final=False, + errorhandler=None): + # XXX MultiByteToWideChar should be used instead. + return str_decode_latin_1(s, size, errors="replace", + final=final, errorhandler=errorhandler) + + def unicode_encode_mbcs(p, size, errors, errorhandler=None): + # XXX This is only roughly correct, even on a Western Windows. + # For example, some greek letters do have a translation (phi -> f) + # WideCharToMultiByte should be used instead. + return unicode_encode_latin_1(p, size, errors="replace", + errorhandler=errorhandler) From fijall at gmail.com Sat Feb 7 08:39:40 2009 From: fijall at gmail.com (Maciej Fijalkowski) Date: Sat, 7 Feb 2009 08:39:40 +0100 Subject: [pypy-svn] r61600 - in pypy/trunk/pypy: module/_codecs module/_codecs/test rlib In-Reply-To: <20090206223719.35A7816A026@codespeak.net> References: <20090206223719.35A7816A026@codespeak.net> Message-ID: <693bc9ab0902062339s6cb5f8f9o1ae3e8fb0f7a5985@mail.gmail.com> On Fri, Feb 6, 2009 at 11:37 PM, wrote: > Author: afa > Date: Fri Feb ?6 23:37:18 2009 > New Revision: 61600 > > Modified: > ? pypy/trunk/pypy/module/_codecs/__init__.py > ? pypy/trunk/pypy/module/_codecs/interp_codecs.py > ? pypy/trunk/pypy/module/_codecs/test/test_codecs.py > ? pypy/trunk/pypy/rlib/runicode.py > Log: > Provide an approximation of the mbcs codec, almost correct > on a Western installation of Windows (cp1252). > > I do have a working complete implementation based on WideCharToMultiByte, > but it needs a lot of missing functions from rffi: > get_nonmoving_unicodebuffer, unicode_from_buffer &co > that I don't want to submit just before the sprint :-) > > nonmoving buffer is just an optimization. (it's even unclear how good this optimization is). You can achieve the same by having a list of unichars. Then you just do u''.join(l). Feel free to hack on it, it's rather a micro-sprint and we didn't touch pypy yet at all :) Cheers, fijal From fijal at codespeak.net Sat Feb 7 13:11:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Feb 2009 13:11:20 +0100 (CET) Subject: [pypy-svn] r61602 - pypy/trunk/pypy/interpreter/test Message-ID: <20090207121120.852A516A05D@codespeak.net> Author: fijal Date: Sat Feb 7 13:11:19 2009 New Revision: 61602 Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py Log: (everyone) A (failing) test for optimize Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_compiler.py (original) +++ pypy/trunk/pypy/interpreter/test/test_compiler.py Sat Feb 7 13:11:19 2009 @@ -766,6 +766,23 @@ output = s.getvalue() assert 'BINARY_ADD' not in output + def test_remove_ending(self): + source = """def f(): + return 3 +""" + exec source + code = f.func_code + import dis, sys, StringIO + s = StringIO.StringIO() + so = sys.stdout + sys.stdout = s + try: + dis.dis(code) + finally: + sys.stdout = so + output = s.getvalue() + assert output.count('LOAD_CONST') == 1 + class AppTestExceptions: def test_indentation_error(self): source = """if 1: From laszlo at codespeak.net Sat Feb 7 13:45:22 2009 From: laszlo at codespeak.net (laszlo at codespeak.net) Date: Sat, 7 Feb 2009 13:45:22 +0100 (CET) Subject: [pypy-svn] r61603 - pypy/trunk/pypy/interpreter/astcompiler Message-ID: <20090207124522.B769C16A011@codespeak.net> Author: laszlo Date: Sat Feb 7 13:45:21 2009 New Revision: 61603 Modified: pypy/trunk/pypy/interpreter/astcompiler/pyassem.py Log: (laszlo, fijal, everyone) Fix for a peepholer test Modified: pypy/trunk/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/trunk/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/trunk/pypy/interpreter/astcompiler/pyassem.py Sat Feb 7 13:45:21 2009 @@ -15,6 +15,7 @@ def __init__(self, space, name, filename, argnames=None, optimized=0, klass=0, newlocals=0): self.space = space + self.deadcode = False if argnames is None: argnames = [] self.name = name @@ -74,7 +75,12 @@ # Simple instructions def emit(self, opname): + if self.deadcode: + return + self.co_code.append(chr(pythonopcode.opmap[opname])) + if opname in ops_unconditional: + self.deadcode = True def emitop_extended_arg(self, intval): assert intval <= 0x7FFFFFFF @@ -217,14 +223,17 @@ def newBlock(self): """This really returns a new label, initially not pointing anywhere.""" + self.deadcode = False return Label() def nextBlock(self, label): + self.deadcode = False if label.position >= 0: raise InternalCompilerError("Label target already seen") label.position = len(self.co_code) def emitop_block(self, opname, label): + self.deadcode = False absolute = opname in self.hasjabs target = label.position if target < 0: # unknown yet @@ -604,6 +613,8 @@ ops_jump_unconditionally = ('JUMP_ABSOLUTE', 'JUMP_FORWARD') ops_jumps = list(PyFlowGraph.hasjrel) + list(PyFlowGraph.hasjabs) +ops_unconditional = ops_jump_unconditionally + ops_interrupt_unconditionally + DEPTH_OP_TRACKER = {} DEPTH_OP_EFFECT_ALONG_JUMP = {} setup_stack_depth_tracker() From fijal at codespeak.net Sat Feb 7 13:50:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Feb 2009 13:50:58 +0100 (CET) Subject: [pypy-svn] r61604 - pypy/trunk/pypy/interpreter/test Message-ID: <20090207125058.ECB2116A056@codespeak.net> Author: fijal Date: Sat Feb 7 13:50:58 2009 New Revision: 61604 Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py Log: another failing test from test_peepholer Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_compiler.py (original) +++ pypy/trunk/pypy/interpreter/test/test_compiler.py Sat Feb 7 13:50:58 2009 @@ -783,6 +783,53 @@ output = s.getvalue() assert output.count('LOAD_CONST') == 1 + + def test_folding_of_binops_on_constants(self): + def disassemble(func): + from StringIO import StringIO + import sys, dis + f = StringIO() + tmp = sys.stdout + sys.stdout = f + dis.dis(func) + sys.stdout = tmp + result = f.getvalue() + f.close() + return result + + def dis_single(line): + return disassemble(compile(line, '', 'single')) + + for line, elem in ( + ('a = 2+3+4', '(9)'), # chained fold + ('"@"*4', "('@@@@')"), # check string ops + ('a="abc" + "def"', "('abcdef')"), # check string ops + ('a = 3**4', '(81)'), # binary power + ('a = 3*4', '(12)'), # binary multiply + ('a = 13//4', '(3)'), # binary floor divide + ('a = 14%4', '(2)'), # binary modulo + ('a = 2+3', '(5)'), # binary add + ('a = 13-4', '(9)'), # binary subtract + ('a = (12,13)[1]', '(13)'), # binary subscr + ('a = 13 << 2', '(52)'), # binary lshift + ('a = 13 >> 2', '(3)'), # binary rshift + ('a = 13 & 7', '(5)'), # binary and + ('a = 13 ^ 7', '(10)'), # binary xor + ('a = 13 | 7', '(15)'), # binary or + ): + asm = dis_single(line) + assert elem in asm + assert 'BINARY_' not in asm + + # Verify that unfoldables are skipped + asm = dis_single('a=2+"b"') + assert '(2)' in asm + assert "('b')" in asm + + # Verify that large sequences do not result from folding + asm = dis_single('a="x"*1000') + assert '(1000)' in asm + class AppTestExceptions: def test_indentation_error(self): source = """if 1: From laszlo at codespeak.net Sat Feb 7 15:50:51 2009 From: laszlo at codespeak.net (laszlo at codespeak.net) Date: Sat, 7 Feb 2009 15:50:51 +0100 (CET) Subject: [pypy-svn] r61606 - pypy/trunk/pypy/interpreter/test Message-ID: <20090207145051.384D8169E2F@codespeak.net> Author: laszlo Date: Sat Feb 7 15:50:50 2009 New Revision: 61606 Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py Log: Disabled test of subscritpion Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_compiler.py (original) +++ pypy/trunk/pypy/interpreter/test/test_compiler.py Sat Feb 7 15:50:50 2009 @@ -810,7 +810,7 @@ ('a = 14%4', '(2)'), # binary modulo ('a = 2+3', '(5)'), # binary add ('a = 13-4', '(9)'), # binary subtract - ('a = (12,13)[1]', '(13)'), # binary subscr + # ('a = (12,13)[1]', '(13)'), # binary subscr - pointless optimization ('a = 13 << 2', '(52)'), # binary lshift ('a = 13 >> 2', '(3)'), # binary rshift ('a = 13 & 7', '(5)'), # binary and @@ -818,8 +818,9 @@ ('a = 13 | 7', '(15)'), # binary or ): asm = dis_single(line) - assert elem in asm - assert 'BINARY_' not in asm + print asm + assert elem in asm, 'ELEMENT not in asm' + assert 'BINARY_' not in asm, 'BINARY_in_asm' # Verify that unfoldables are skipped asm = dis_single('a=2+"b"') From arigo at codespeak.net Sat Feb 7 16:34:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Feb 2009 16:34:30 +0100 (CET) Subject: [pypy-svn] r61609 - pypy/trunk/pypy/lib Message-ID: <20090207153430.85A8F169FCE@codespeak.net> Author: arigo Date: Sat Feb 7 16:34:30 2009 New Revision: 61609 Modified: pypy/trunk/pypy/lib/_pypy_interact.py Log: Check in advance if readline can really be initialized. Fixes test_i_flag_overrides_isatty in translator/goal/test/test_app_main.py. Modified: pypy/trunk/pypy/lib/_pypy_interact.py ============================================================================== --- pypy/trunk/pypy/lib/_pypy_interact.py (original) +++ pypy/trunk/pypy/lib/_pypy_interact.py Sat Feb 7 16:34:30 2009 @@ -16,6 +16,9 @@ except ImportError: pass try: + from pyrepl.simple_interact import check + if not check(): + raise ImportError from pyrepl.simple_interact import run_multiline_interactive_console except ImportError: run_simple_interactive_console(mainmodule) From arigo at codespeak.net Sat Feb 7 16:38:07 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Feb 2009 16:38:07 +0100 (CET) Subject: [pypy-svn] r61610 - pypy/trunk/pypy/rlib/test Message-ID: <20090207153807.E8D04169FCE@codespeak.net> Author: arigo Date: Sat Feb 7 16:38:06 2009 New Revision: 61610 Modified: pypy/trunk/pypy/rlib/test/test_rpoll.py Log: Split test_select() in two parts to know more precisely which part fails occasionally on http://codespeak.net:8099/summary . Increased the delay from 1.0 to 5.0 seconds, which (if it is the problem) might solve it. Modified: pypy/trunk/pypy/rlib/test/test_rpoll.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_rpoll.py (original) +++ pypy/trunk/pypy/rlib/test/test_rpoll.py Sat Feb 7 16:38:06 2009 @@ -50,7 +50,6 @@ serv.close() def test_select(): - from time import time def f(): readend, writeend = os.pipe() try: @@ -64,16 +63,20 @@ finally: os.close(readend) os.close(writeend) + f() + interpret(f, []) +def test_select_timeout(): + from time import time + def f(): # once there was a bug where the sleeping time was doubled a = time() - iwtd, owtd, ewtd = select([], [], [], 1.0) + iwtd, owtd, ewtd = select([], [], [], 5.0) diff = time() - a - assert 0.9 < diff < 1.1 - - f() + assert 4.8 < diff < 9.0 interpret(f, []) + def test_translate(): from pypy.translator.c.test.test_genc import compile From arigo at codespeak.net Sat Feb 7 16:47:20 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Feb 2009 16:47:20 +0100 (CET) Subject: [pypy-svn] r61611 - pypy/trunk/lib-python Message-ID: <20090207154720.574AE169FE6@codespeak.net> Author: arigo Date: Sat Feb 7 16:47:17 2009 New Revision: 61611 Modified: pypy/trunk/lib-python/failure_list.txt Log: Update this list. Modified: pypy/trunk/lib-python/failure_list.txt ============================================================================== --- pypy/trunk/lib-python/failure_list.txt (original) +++ pypy/trunk/lib-python/failure_list.txt Sat Feb 7 16:47:17 2009 @@ -19,7 +19,6 @@ test_import importing from pyc-files-without-py-file disabled by default test_iterlen somehow implementation detail (missing __length_hint__()) test_itertools same as test_iterlen -test_logging ! exception classes have different repr than the rest in cpython test_normalization test skipped test_parser missing parser.compilest(). I don't think we care for now test_peepholer implementation detail (might be useful to look, though) @@ -30,16 +29,11 @@ test_pyclbr ! this import should find test/pyclbr_input.py test_pyexpat is that an implementation detail? test_repr implementation detail -test_shelve ! unknown -test_signal ! missing signal.alarm(), probably easy to add -test_site ! fix me test_socketserver test skipped test_sqlite ! why no sqlite available? test_structmembers CPython-only -test_subprocess ! missing resource.error. no clue about os.fpathconf(). -test_syntax more small hacking here and there in the ast compiler +test_subprocess missing os.fpathconf(). test_sys missing sys._current_frames() -test_tarfile ! timeout? test_thread the docs say it's ok to raise thread.error here, but maybe we need to have thread.stack_size() implemented anyway (no hurry I'd say) test_timeout skipped test test_trace probably all acceptable differences @@ -50,8 +44,6 @@ test_urllibnet skipped test test_wait3 no os.wait3() test_wait4 no os.wait4() -test_weakref probably missing some gc.collect() -test_with minor hacking in the ast compiler test_xmlrpc sys.setdefaultencoding missing test_zipfile64 skipped test From fijal at codespeak.net Sat Feb 7 17:18:21 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 7 Feb 2009 17:18:21 +0100 (CET) Subject: [pypy-svn] r61613 - pypy/trunk/lib-python Message-ID: <20090207161821.CA767169FF7@codespeak.net> Author: fijal Date: Sat Feb 7 17:18:21 2009 New Revision: 61613 Removed: pypy/trunk/lib-python/failure_list.txt Log: We don't seem to need this file any more, we have only 3 failures From laszlo at codespeak.net Sat Feb 7 17:22:35 2009 From: laszlo at codespeak.net (laszlo at codespeak.net) Date: Sat, 7 Feb 2009 17:22:35 +0100 (CET) Subject: [pypy-svn] r61614 - in pypy/trunk: lib-python/modified-2.5.2/test pypy/interpreter/astcompiler Message-ID: <20090207162235.199CF16A01D@codespeak.net> Author: laszlo Date: Sat Feb 7 17:22:32 2009 New Revision: 61614 Added: pypy/trunk/lib-python/modified-2.5.2/test/test_peepholer.py (contents, props changed) - copied, changed from r61602, pypy/trunk/lib-python/2.5.2/test/test_peepholer.py Modified: pypy/trunk/pypy/interpreter/astcompiler/opt.py Log: (fijal, laszlo, mastier) Hack at test_peepholer, until it works. Copied: pypy/trunk/lib-python/modified-2.5.2/test/test_peepholer.py (from r61602, pypy/trunk/lib-python/2.5.2/test/test_peepholer.py) ============================================================================== --- pypy/trunk/lib-python/2.5.2/test/test_peepholer.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_peepholer.py Sat Feb 7 17:22:32 2009 @@ -2,6 +2,7 @@ import sys from cStringIO import StringIO import unittest +from test_support import check_impl_detail def disassemble(func): f = StringIO() @@ -70,8 +71,8 @@ def test_pack_unpack(self): for line, elem in ( ('a, = a,', 'LOAD_CONST',), - ('a, b = a, b', 'ROT_TWO',), - ('a, b, c = a, b, c', 'ROT_THREE',), + ('x[3], x[4] = a, b', 'ROT_TWO',), + ('x[1], x[2], x[3] = a, b, c', 'ROT_THREE',), ): asm = dis_single(line) self.assert_(elem in asm) @@ -82,9 +83,9 @@ for line, elem in ( ('a = 1,2,3', '((1, 2, 3))'), ('("a","b","c")', "(('a', 'b', 'c'))"), - ('a,b,c = 1,2,3', '((1, 2, 3))'), - ('(None, 1, None)', '((None, 1, None))'), - ('((1, 2), 3, 4)', '(((1, 2), 3, 4))'), + ('a,b,c = 1,2,3', ''), # empty string - we only care to check BUILD_TUPLE + ('x = (None, 1, None)', '((None, 1, None))'), + ('x = ((1, 2), 3, 4)', '(((1, 2), 3, 4))'), ): asm = dis_single(line) self.assert_(elem in asm) @@ -118,13 +119,15 @@ ('a = 14%4', '(2)'), # binary modulo ('a = 2+3', '(5)'), # binary add ('a = 13-4', '(9)'), # binary subtract - ('a = (12,13)[1]', '(13)'), # binary subscr + ('a = (12,13)[1]#detail', '(13)'), # binary subscr ('a = 13 << 2', '(52)'), # binary lshift ('a = 13 >> 2', '(3)'), # binary rshift ('a = 13 & 7', '(5)'), # binary and ('a = 13 ^ 7', '(10)'), # binary xor ('a = 13 | 7', '(15)'), # binary or ): + if line.endswith('#detail') and not check_impl_detail(): + continue asm = dis_single(line) self.assert_(elem in asm, asm) self.assert_('BINARY_' not in asm) Modified: pypy/trunk/pypy/interpreter/astcompiler/opt.py ============================================================================== --- pypy/trunk/pypy/interpreter/astcompiler/opt.py (original) +++ pypy/trunk/pypy/interpreter/astcompiler/opt.py Sat Feb 7 17:22:32 2009 @@ -240,9 +240,12 @@ consts_w = [None] * len(nodes) for i in range(len(nodes)): subnode = nodes[i] - if not isinstance(subnode, ast.Const): + if isinstance(subnode, ast.Const): + consts_w[i] = subnode.value + elif isinstance(subnode, ast.Name) and subnode.varname == 'None': + consts_w[i] = self.space.w_None + else: return node # not all constants - consts_w[i] = subnode.value return ast.Const(self.space.newtuple(consts_w)) def visitFor(self, node): From arigo at codespeak.net Sat Feb 7 17:34:13 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 7 Feb 2009 17:34:13 +0100 (CET) Subject: [pypy-svn] r61615 - pypy/trunk/pypy/translator/sandbox/test Message-ID: <20090207163413.37ACE169F79@codespeak.net> Author: arigo Date: Sat Feb 7 17:34:12 2009 New Revision: 61615 Modified: pypy/trunk/pypy/translator/sandbox/test/test_sandbox.py pypy/trunk/pypy/translator/sandbox/test/test_sandlib.py Log: Fix the tests to use gc='ref' instead of the now-default gc='hybrid'. This avoids the initial calls to os.getenv() done by the generation GC. Modified: pypy/trunk/pypy/translator/sandbox/test/test_sandbox.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/test/test_sandbox.py (original) +++ pypy/trunk/pypy/translator/sandbox/test/test_sandbox.py Sat Feb 7 17:34:12 2009 @@ -19,6 +19,10 @@ write_message(g, result, resulttype) g.flush() +def compile(f): + t = Translation(f, backend='c', standalone=True, sandbox=True, gc='ref') + return str(t.compile()) + def test_open_dup(): def entry_point(argv): @@ -28,8 +32,7 @@ assert fd2 == 78 return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) g, f = os.popen2(exe, "t", 0) expect(f, g, "ll_os.ll_os_open", ("/tmp/foobar", os.O_RDONLY, 0777), 77) expect(f, g, "ll_os.ll_os_dup", (77,), 78) @@ -49,8 +52,7 @@ os.close(fd) return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) g, f = os.popen2(exe, "t", 0) expect(f, g, "ll_os.ll_os_open", ("/tmp/foobar", os.O_RDONLY, 0777), 77) expect(f, g, "ll_os.ll_os_read", (77, 123), "he\x00llo") @@ -67,8 +69,7 @@ y = os.access("spam", 77) return 1 - y - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) g, f = os.popen2(exe, "t", 0) expect(f, g, "ll_os.ll_os_dup2", (34, 56), None) expect(f, g, "ll_os.ll_os_access", ("spam", 77), True) @@ -87,8 +88,7 @@ os.ftruncate(st.st_mode, st.st_size) # nonsense, just to see outside return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) g, f = os.popen2(exe, "t", 0) st = os.stat_result((55, 0, 0, 0, 0, 0, 0x12380000007, 0, 0, 0)) expect(f, g, "ll_os.ll_os_stat", ("somewhere",), st, @@ -105,8 +105,7 @@ os.dup(int(t*1000)) return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) g, f = os.popen2(exe, "t", 0) expect(f, g, "ll_time.ll_time_time", (), 3.141592) expect(f, g, "ll_os.ll_os_dup", (3141,), 3) @@ -123,8 +122,7 @@ os.close(e.errno) # nonsense, just to see outside return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) g, f = os.popen2(exe, "t", 0) expect(f, g, "ll_os.ll_os_stat", ("somewhere",), OSError(6321, "egg")) expect(f, g, "ll_os.ll_os_close", (6321,), None) @@ -136,9 +134,7 @@ class TestPrintedResults: def run(self, entry_point, args, expected): - t = Translation(entry_point, backend='c', standalone=True, - sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc proc = SimpleIOSandboxedProc([exe] + args) output, error = proc.communicate() Modified: pypy/trunk/pypy/translator/sandbox/test/test_sandlib.py ============================================================================== --- pypy/trunk/pypy/translator/sandbox/test/test_sandlib.py (original) +++ pypy/trunk/pypy/translator/sandbox/test/test_sandlib.py Sat Feb 7 17:34:12 2009 @@ -5,7 +5,7 @@ from pypy.translator.sandbox.sandlib import SandboxedProc from pypy.translator.sandbox.sandlib import SimpleIOSandboxedProc from pypy.translator.sandbox.sandlib import VirtualizedSocketProc -from pypy.translator.interactive import Translation +from pypy.translator.sandbox.test.test_sandbox import compile class MySandboxedProc(SandboxedProc): @@ -46,8 +46,7 @@ assert count == 61 os.close(fd) return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) proc = MySandboxedProc([exe, 'x1', 'y2'], expected = [ ("open", ("/tmp/foobar", os.O_RDONLY, 0777), 77), @@ -68,8 +67,7 @@ s = rffi.str2charp(argv[1]); n = foobar(s); rffi.free_charp(s) s = rffi.str2charp(argv[n]); n = foobar(s); rffi.free_charp(s) return n - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) proc = MySandboxedProc([exe, 'spam', 'egg'], expected = [ ("foobar", ("spam",), 2), @@ -92,8 +90,7 @@ num = int(buf) print "The double is:", num * 2 return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) proc = SimpleIOSandboxedProc([exe, 'x1', 'y2']) output, error = proc.communicate("21\n") @@ -110,8 +107,7 @@ os.write(fd, 'GET /\n') print os.read(fd, 30) return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) proc = SocketProc([exe]) output, error = proc.communicate("") @@ -124,8 +120,7 @@ except OSError, e: os.close(e.errno) # nonsense, just to see outside return 0 - t = Translation(entry_point, backend='c', standalone=True, sandbox=True) - exe = str(t.compile()) + exe = compile(entry_point) proc = MySandboxedProc([exe], expected = [ ("open", ("/tmp/foobar", os.O_RDONLY, 0777), OSError(-42, "baz")), From arigo at codespeak.net Sun Feb 8 18:12:11 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 8 Feb 2009 18:12:11 +0100 (CET) Subject: [pypy-svn] r61640 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090208171211.6657916A0F6@codespeak.net> Author: arigo Date: Sun Feb 8 18:12:10 2009 New Revision: 61640 Modified: pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py Log: Skip this test on top of Python 2.4 or earlier, which shows the same strange corner case for unicode.rfind(). Modified: pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py Sun Feb 8 18:12:10 2009 @@ -39,6 +39,10 @@ class AppTestUnicodeString: + def setup_class(cls): + import sys + cls.w_version_info = cls.space.wrap(sys.version_info) + def test_addition(self): def check(a, b): assert a == b @@ -571,6 +575,10 @@ assert u'abcdefghiabc'.rfind(u'') == 12 assert u'abcdefghiabc'.rfind(u'abcd') == 0 assert u'abcdefghiabc'.rfind(u'abcz') == -1 + + def test_rfind_corner_case(self): + if self.version_info < (2, 5): + skip("fails on top of CPython <= 2.4") assert u'abc'.rfind('', 4) == -1 def test_count(self): From afa at codespeak.net Mon Feb 9 10:02:03 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 10:02:03 +0100 (CET) Subject: [pypy-svn] r61644 - pypy/trunk/pypy/module/_rawffi/test Message-ID: <20090209090203.0F01A16A04D@codespeak.net> Author: afa Date: Mon Feb 9 10:02:02 2009 New Revision: 61644 Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Log: Fix _rawffi tests on Win32 Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Mon Feb 9 10:02:02 2009 @@ -297,7 +297,11 @@ def test_time(self): import _rawffi libc = _rawffi.get_libc() - time = libc.ptr('time', ['z'], 'l') # 'z' instead of 'P' just for test + try: + time = libc.ptr('time', ['z'], 'l') # 'z' instead of 'P' just for test + except AttributeError: + # Since msvcr80, this function is named differently + time = libc.ptr('_time32', ['z'], 'l') arg = _rawffi.Array('P')(1) arg[0] = 0 res = time(arg) @@ -346,7 +350,11 @@ ("tm_yday", 'i'), ("tm_isdst", 'i')]) libc = _rawffi.get_libc() - gmtime = libc.ptr('gmtime', ['P'], 'P') + try: + gmtime = libc.ptr('gmtime', ['P'], 'P') + except AttributeError: + # Since msvcr80, this function is named differently + gmtime = libc.ptr('_gmtime32', ['P'], 'P') arg = x.byptr() res = gmtime(arg) @@ -615,7 +623,7 @@ a.free() def test_wide_char(self): - import _rawffi + import _rawffi, sys A = _rawffi.Array('u') a = A(3) a[0] = u'x' @@ -623,11 +631,18 @@ a[2] = u'z' assert a[0] == u'x' b = _rawffi.Array('c').fromaddress(a.buffer, 38) - assert b[0] == 'x' - assert b[1] == '\x00' - assert b[2] == '\x00' - assert b[3] == '\x00' - assert b[4] == 'y' + if sys.maxunicode > 65535: + # UCS4 build + assert b[0] == 'x' + assert b[1] == '\x00' + assert b[2] == '\x00' + assert b[3] == '\x00' + assert b[4] == 'y' + else: + # UCS2 build + assert b[0] == 'x' + assert b[1] == '\x00' + assert b[2] == 'y' a.free() def test_truncate(self): From antocuni at codespeak.net Mon Feb 9 14:17:38 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 9 Feb 2009 14:17:38 +0100 (CET) Subject: [pypy-svn] r61653 - in pypy/branch/oo-jit/pypy/jit/codegen/cli: . test Message-ID: <20090209131738.54A5B169F5F@codespeak.net> Author: antocuni Date: Mon Feb 9 14:17:37 2009 New Revision: 61653 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Log: add support for int_add_ovf Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Mon Feb 9 14:17:37 2009 @@ -9,6 +9,7 @@ class Operation(object): _gv_res = None + _gv_excflag = None def restype(self): return self.gv_x.getCliType() @@ -20,6 +21,11 @@ self._gv_res = self.meth.newlocalvar(restype) return self._gv_res + def gv_excflag(self): + if self._gv_excflag is None: + self._gv_excflag = self.meth.newlocalvar(typeof(System.Int32)) + return self._gv_excflag + def emit(self): raise NotImplementedError @@ -29,6 +35,9 @@ def storeResult(self): self.gv_res().store(self.meth) + def storeExcFlag(self): + self.gv_excflag().store(self.meth) + class UnaryOp(Operation): def __init__(self, meth, gv_x): @@ -331,6 +340,25 @@ def emit(self): self.meth.il.EmitWriteLine(self.message) +class IntAddOvf(BinaryOp): + + def getOpCode(self): + return OpCodes.Add_Ovf + + def emit(self): + il = self.meth.il + lbl = il.BeginExceptionBlock() + self.pushAllArgs() + il.Emit(self.getOpCode()) + self.storeResult() + il.Emit(OpCodes.Leave, lbl) + + il.BeginCatchBlock(typeof(System.OverflowException)) + il.Emit(OpCodes.Ldc_I4, 1) + self.storeExcFlag() + il.EndExceptionBlock() + + def opcode2attrname(opcode): if opcode == 'ldc.r8 0': return 'Ldc_R8, 0' # XXX this is a hack Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Mon Feb 9 14:17:37 2009 @@ -812,6 +812,22 @@ gv_res = op.gv_res() return gv_res +## @specialize.arg(1) +## def genraisingop1(self, opname, gv_arg): +## return a pair (gv_result, gv_flag_set_if_exception) + + @specialize.arg(1) + def genraisingop2(self, opname, gv_arg1, gv_arg2): + if opname == 'int_add_ovf': + opcls = ops.IntAddOvf + op = opcls(self.meth, gv_arg1, gv_arg2) + self.appendop(op) + gv_res = op.gv_res() + gv_excflag = op.gv_excflag() + return gv_res, gv_excflag + else: + assert False + def genop_call(self, sigtoken, gv_fnptr, args_gv): op = ops.Call(self.meth, sigtoken, gv_fnptr, args_gv) self.appendop(op) Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Mon Feb 9 14:17:37 2009 @@ -66,9 +66,6 @@ def test_from_random_5_direct(self): py.test.skip('mono crash') - def test_ovfcheck_adder_direct(self): - py.test.skip('fixme') - def test_ovfcheck1_direct(self): py.test.skip('fixme') @@ -137,8 +134,5 @@ def test_genconst_from_frame_float_var_compile(self): py.test.skip('fixme: add support for frames') - def test_ovfcheck_adder_compile(self): - py.test.skip('fixme') - def test_ovfcheck1_compile(self): py.test.skip('fixme') From afa at codespeak.net Mon Feb 9 15:25:03 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 15:25:03 +0100 (CET) Subject: [pypy-svn] r61658 - pypy/trunk/pypy/module/unicodedata/test Message-ID: <20090209142503.8BCDB16A05D@codespeak.net> Author: afa Date: Mon Feb 9 15:25:00 2009 New Revision: 61658 Modified: pypy/trunk/pypy/module/unicodedata/test/test_unicodedata.py Log: Please test our unicodedata module and not the faked one from CPython Modified: pypy/trunk/pypy/module/unicodedata/test/test_unicodedata.py ============================================================================== --- pypy/trunk/pypy/module/unicodedata/test/test_unicodedata.py (original) +++ pypy/trunk/pypy/module/unicodedata/test/test_unicodedata.py Mon Feb 9 15:25:00 2009 @@ -4,6 +4,10 @@ from pypy.module.unicodedata import unicodedb_4_1_0 class AppTestUnicodeData: + def setup_class(cls): + space = gettestobjspace(usemodules=('unicodedata',)) + cls.space = space + def test_hangul_syllables(self): import unicodedata # Test all leading, vowel and trailing jamo From arigo at codespeak.net Mon Feb 9 15:47:02 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 9 Feb 2009 15:47:02 +0100 (CET) Subject: [pypy-svn] r61660 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090209144702.94B4416A13C@codespeak.net> Author: arigo Date: Mon Feb 9 15:46:59 2009 New Revision: 61660 Modified: pypy/trunk/pypy/objspace/std/test/test_ropeobject.py pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py Log: This test was split in two, and it's "test_rfind_corner_case" that we want to skip. Modified: pypy/trunk/pypy/objspace/std/test/test_ropeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_ropeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_ropeobject.py Mon Feb 9 15:46:59 2009 @@ -80,7 +80,7 @@ def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withrope": True}) - def test_rfind(self): + def test_rfind_corner_case(self): skip("XXX Fix") class AppTestPrebuilt(AppTestRopeObject): Modified: pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py Mon Feb 9 15:46:59 2009 @@ -46,7 +46,7 @@ def test_replace_with_buffer(self): skip("XXX fix") - def test_rfind(self): + def test_rfind_corner_case(self): skip("XXX fix") def test_rsplit(self): From fijal at codespeak.net Mon Feb 9 15:49:36 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 9 Feb 2009 15:49:36 +0100 (CET) Subject: [pypy-svn] r61661 - pypy/trunk/pypy/translator/c/test Message-ID: <20090209144936.2C16516A0F2@codespeak.net> Author: fijal Date: Mon Feb 9 15:49:35 2009 New Revision: 61661 Modified: pypy/trunk/pypy/translator/c/test/test_newgc.py Log: (arigo, fijal) Skip the long-taking test, with a good explanation Modified: pypy/trunk/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/trunk/pypy/translator/c/test/test_newgc.py (original) +++ pypy/trunk/pypy/translator/c/test/test_newgc.py Mon Feb 9 15:49:35 2009 @@ -747,6 +747,7 @@ def test_dict_segfault(self): " was segfaulting at one point see rev 39665 for fix and details " + py.test.skip("Takes about 30 minutes in nightly test run, see rev 39665 for a minimal test that does the same") class Element: pass From arigo at codespeak.net Mon Feb 9 16:22:58 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 9 Feb 2009 16:22:58 +0100 (CET) Subject: [pypy-svn] r61663 - in pypy/trunk/pypy: config interpreter interpreter/astcompiler interpreter/pyparser/data interpreter/pyparser/test interpreter/test module/_file/test module/marshal module/recparser module/symbol Message-ID: <20090209152258.3B2BC16A10C@codespeak.net> Author: arigo Date: Mon Feb 9 16:22:57 2009 New Revision: 61663 Removed: pypy/trunk/pypy/interpreter/pyparser/data/Grammar2.3 pypy/trunk/pypy/interpreter/pyparser/data/Grammar2.4 Modified: pypy/trunk/pypy/config/pypyoption.py pypy/trunk/pypy/interpreter/astcompiler/pycodegen.py pypy/trunk/pypy/interpreter/pycompiler.py pypy/trunk/pypy/interpreter/pyparser/test/test_astbuilder.py pypy/trunk/pypy/interpreter/pyparser/test/test_pytokenizer.py pypy/trunk/pypy/interpreter/test/test_compiler.py pypy/trunk/pypy/interpreter/test/test_syntax.py pypy/trunk/pypy/module/_file/test/test_file.py pypy/trunk/pypy/module/marshal/interp_marshal.py pypy/trunk/pypy/module/recparser/compat.py pypy/trunk/pypy/module/symbol/__init__.py Log: (fijal, arigo) Kill the --pyversion command-line option. Always use 2.5 for now. Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Mon Feb 9 16:22:57 2009 @@ -110,10 +110,6 @@ ["cpython", "ast"], "ast", cmdline='--compiler'), - ChoiceOption("pyversion", "which grammar to use for app-level code", - ["2.3", "2.4", "2.5"], "2.5", - cmdline='--pyversion'), - OptionDescription("opcodes", "opcodes to enable in the interpreter", [ BoolOption("CALL_LIKELY_BUILTIN", "emit a special bytecode for likely calls to builtin functions", default=False, Modified: pypy/trunk/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/trunk/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/trunk/pypy/interpreter/astcompiler/pycodegen.py Mon Feb 9 16:22:57 2009 @@ -1143,13 +1143,6 @@ self.emit('RETURN_VALUE') def visitYield(self, node): - if self.space.config.objspace.pyversion < '2.5': - if len(self.setups): - kind, block = self.setups[-1] - if kind == TRY_FINALLY: - raise SyntaxError("'yield' not allowed in a 'try' block " - "with a 'finally' clause", - node.lineno) self.set_lineno(node) node.value.accept( self ) self.emit('YIELD_VALUE') Modified: pypy/trunk/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/trunk/pypy/interpreter/pycompiler.py (original) +++ pypy/trunk/pypy/interpreter/pycompiler.py Mon Feb 9 16:22:57 2009 @@ -217,7 +217,7 @@ from pyparser.pythonparse import make_pyparser PyCodeCompiler.__init__(self, space) - self.grammar_version = override_version or space.config.objspace.pyversion + self.grammar_version = override_version or "2.5" self.parser = make_pyparser(self.grammar_version) self.additional_rules = {} if self.grammar_version >= '2.5': Modified: pypy/trunk/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/trunk/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/trunk/pypy/interpreter/pyparser/test/test_astbuilder.py Mon Feb 9 16:22:57 2009 @@ -188,13 +188,13 @@ t = Transformer("dummyfile") return ast_from_input(expr, target, t, stable_parser) -def source2ast(source, mode, space=FakeSpace(), version='2.4'): +def source2ast(source, mode, space=FakeSpace(), version='2.5'): python_parser = pythonparse.make_pyparser(version) builder = AstBuilder(python_parser, version, space=space) python_parser.parse_source(source, mode, builder) return builder.rule_stack[-1] -def check_expression(expr, mode='single', version='2.4'): +def check_expression(expr, mode='single', version='2.5'): pypy_ast = source2ast(expr, mode, version=version) try: python_ast = EXPECTED[expr] Modified: pypy/trunk/pypy/interpreter/pyparser/test/test_pytokenizer.py ============================================================================== --- pypy/trunk/pypy/interpreter/pyparser/test/test_pytokenizer.py (original) +++ pypy/trunk/pypy/interpreter/pyparser/test/test_pytokenizer.py Mon Feb 9 16:22:57 2009 @@ -3,7 +3,7 @@ from pypy.interpreter.pyparser.grammar import Token, GrammarElement from pypy.interpreter.pyparser.pythonparse import make_pyparser, _check_for_encoding -P = make_pyparser('2.4') +P = make_pyparser('2.5') EQUAL = P.tokens['EQUAL'] ENDMARKER = P.tokens['ENDMARKER'] Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_compiler.py (original) +++ pypy/trunk/pypy/interpreter/test/test_compiler.py Mon Feb 9 16:22:57 2009 @@ -255,10 +255,7 @@ def test_yield_in_finally(self): code ='def f():\n try:\n yield 19\n finally:\n pass\n' - e = py.test.raises(OperationError, self.compiler.compile, code, '', 'single', 0) - ex = e.value - ex.normalize_exception(self.space) - assert ex.match(self.space, self.space.w_SyntaxError) + self.compiler.compile(code, '', 'single', 0) def test_none_assignment(self): stmts = [ @@ -651,10 +648,7 @@ py.test.skip("syntax not supported by the CPython 2.4 compiler") test_continue_in_nested_finally = skip_on_2_4 test_try_except_finally = skip_on_2_4 - elif sys.version_info > (2, 4): - def skip_on_2_5(self): - py.test.skip("syntax changed in CPython 2.5 compiler") - test_yield_in_finally = skip_on_2_5 + test_yield_in_finally = skip_on_2_4 class TestPythonAstCompiler_25_grammar(BaseTestCompiler): def setup_method(self, method): @@ -690,10 +684,6 @@ else: py.test.fail("Did not raise") - def test_yield_in_finally(self): # behavior changed in 2.5 - code ='def f():\n try:\n yield 19\n finally:\n pass\n' - self.compiler.compile(code, '', 'single', 0) - def test_assign_to_yield(self): code = 'def f(): (yield bar) += y' try: @@ -716,17 +706,15 @@ class TestECCompiler(BaseTestCompiler): def setup_method(self, method): - self.space.config.objspace.pyversion = "2.4" self.compiler = self.space.getexecutioncontext().compiler -class TestPythonAstCompiler(BaseTestCompiler): - def setup_method(self, method): - self.space.config.objspace.pyversion = "2.4" - self.compiler = PythonAstCompiler(self.space, "2.4") +##class TestPythonAstCompiler(BaseTestCompiler): +## def setup_method(self, method): +## self.compiler = PythonAstCompiler(self.space, "2.4") - def test_try_except_finally(self): - py.test.skip("unsupported") +## def test_try_except_finally(self): +## py.test.skip("unsupported") class AppTestOptimizer: def test_constant_fold_add(self): Modified: pypy/trunk/pypy/interpreter/test/test_syntax.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_syntax.py (original) +++ pypy/trunk/pypy/interpreter/test/test_syntax.py Mon Feb 9 16:22:57 2009 @@ -257,12 +257,7 @@ raise -class Py25AppTest: - def setup_class(self): - self.space = gettestobjspace(pyversion='2.5') - return - -class AppTestCondExpr(Py25AppTest): +class AppTestCondExpr: def test_condexpr(self): for s, expected in [("x = 1 if True else 2", 1), ("x = 1 if False else 2", 2)]: @@ -276,13 +271,13 @@ exec "1 if True else 2" warnings.simplefilter('default', SyntaxWarning) -class AppTestYield(Py25AppTest): +class AppTestYield: def test_bare_yield(self): s = "def f():\n yield" exec s -class AppTestWith(Py25AppTest): +class AppTestWith: def test_with_simple(self): s = """from __future__ import with_statement Modified: pypy/trunk/pypy/module/_file/test/test_file.py ============================================================================== --- pypy/trunk/pypy/module/_file/test/test_file.py (original) +++ pypy/trunk/pypy/module/_file/test/test_file.py Mon Feb 9 16:22:57 2009 @@ -253,7 +253,7 @@ class AppTestFile25: def setup_class(cls): - cls.space = gettestobjspace(usemodules=("_file", ), pyversion="2.5") + cls.space = gettestobjspace(usemodules=("_file", )) cls.w_temppath = cls.space.wrap( str(py.test.ensuretemp("fileimpl").join("foo.txt"))) cls.w_file = getfile(cls.space) Modified: pypy/trunk/pypy/module/marshal/interp_marshal.py ============================================================================== --- pypy/trunk/pypy/module/marshal/interp_marshal.py (original) +++ pypy/trunk/pypy/module/marshal/interp_marshal.py Mon Feb 9 16:22:57 2009 @@ -5,13 +5,7 @@ from pypy.module._file.interp_stream import StreamErrors, wrap_streamerror import sys -# Py_MARSHAL_VERSION = 2 -# this is from Python 2.5 -# already implemented, but for compatibility, -# we default to version 1. Version 2 can be -# tested, anyway, by using the optional parameter. -# XXX make it 2 when used with --pyversion=2.5 translation -Py_MARSHAL_VERSION = 1 +Py_MARSHAL_VERSION = 2 def dump(space, w_data, w_f, w_version=Py_MARSHAL_VERSION): """Write the 'data' object into the open file 'f'.""" Modified: pypy/trunk/pypy/module/recparser/compat.py ============================================================================== --- pypy/trunk/pypy/module/recparser/compat.py (original) +++ pypy/trunk/pypy/module/recparser/compat.py Mon Feb 9 16:22:57 2009 @@ -12,7 +12,7 @@ if not _PARSER: from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=False) - _PARSER = make_pyparser(config.objspace.pyversion) + _PARSER = make_pyparser("2.5") return _PARSER def suite( source ): Modified: pypy/trunk/pypy/module/symbol/__init__.py ============================================================================== --- pypy/trunk/pypy/module/symbol/__init__.py (original) +++ pypy/trunk/pypy/module/symbol/__init__.py Mon Feb 9 16:22:57 2009 @@ -16,10 +16,6 @@ appleveldefs = {} interpleveldefs = {} # see below - def __init__(self, space, w_name): - MixedModule.__init__(self, space, w_name) - _init_symbols(space.config.objspace.pyversion) - # Export the values from our custom symbol module. # Skip negative values (the corresponding symbols are not visible in From afa at codespeak.net Mon Feb 9 17:03:46 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 17:03:46 +0100 (CET) Subject: [pypy-svn] r61664 - in pypy/trunk/pypy: module/__builtin__ module/__builtin__/test module/_codecs/test module/_rawffi module/_rawffi/test module/sys module/unicodedata rlib rlib/rsre rlib/rstruct rlib/test rpython Message-ID: <20090209160346.4E7DA16A14A@codespeak.net> Author: afa Date: Mon Feb 9 17:03:45 2009 New Revision: 61664 Modified: pypy/trunk/pypy/module/__builtin__/operation.py pypy/trunk/pypy/module/__builtin__/test/test_builtin.py pypy/trunk/pypy/module/_codecs/test/test_codecs.py pypy/trunk/pypy/module/_rawffi/interp_rawffi.py pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py pypy/trunk/pypy/module/sys/__init__.py pypy/trunk/pypy/module/sys/vm.py pypy/trunk/pypy/module/unicodedata/interp_ucd.py pypy/trunk/pypy/rlib/libffi.py pypy/trunk/pypy/rlib/rsre/rsre_char.py pypy/trunk/pypy/rlib/rstruct/unichar.py pypy/trunk/pypy/rlib/runicode.py pypy/trunk/pypy/rlib/test/test_runicode.py pypy/trunk/pypy/rpython/rint.py Log: Remove the dependency between the generated pypy and the CPython running the translation. Basically, interp-level code now should use rlib.runicode.MAXUNICODE (instead of sys.maxunicode) MAXUNICODE is determined after the value of rffi.sizeof(lltype.UniChar) which itself is configured after the wchar_t type This allows generation of a UCS4 pypy-c by a UCS2 cpython, and also ensures that unicode objects are compatible with wchar_t* buffers. Modified: pypy/trunk/pypy/module/__builtin__/operation.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/operation.py (original) +++ pypy/trunk/pypy/module/__builtin__/operation.py Mon Feb 9 17:03:45 2009 @@ -5,6 +5,7 @@ from pypy.interpreter import gateway, buffer from pypy.interpreter.baseobjspace import ObjSpace from pypy.interpreter.error import OperationError +from pypy.rlib.runicode import UNICHR import __builtin__ NoneNotWrapped = gateway.NoneNotWrapped @@ -27,7 +28,7 @@ "Return a Unicode string of one character with the given ordinal." # XXX range checking! try: - c = __builtin__.unichr(code) + c = UNICHR(code) except ValueError: raise OperationError(space.w_ValueError, space.wrap("unichr() arg out of range")) Modified: pypy/trunk/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/trunk/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/trunk/pypy/module/__builtin__/test/test_builtin.py Mon Feb 9 17:03:45 2009 @@ -33,9 +33,11 @@ assert unichr(65) == u'A' assert type(unicode(65)) is unicode assert unichr(0x9876) == u'\u9876' - assert ord(unichr(sys.maxunicode)) == sys.maxunicode - if sys.maxunicode > 0x10000: + if sys.maxunicode > 0xFFFF: + assert unichr(sys.maxunicode) == u'\U0010FFFF' assert unichr(0x10000) == u'\U00010000' + else: + assert unichr(sys.maxunicode) == u'\uFFFF' raises(ValueError, unichr, -1) raises(ValueError, unichr, sys.maxunicode+1) Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/test/test_codecs.py Mon Feb 9 17:03:45 2009 @@ -225,7 +225,8 @@ assert enc == "\x00a" else: assert enc == "a\x00" - else: # UCS4 build + elif len(u"\U00010098") == 1: + # UCS4 build on a UCS4 CPython enc2 = u"\U00010098".encode("unicode_internal") if sys.byteorder == "big": assert enc == "\x00\x00\x00a" @@ -233,6 +234,12 @@ else: assert enc == "a\x00\x00\x00" assert enc2 == "\x98\x00\x01\x00" + else: + # UCS4 build on a UCS2 CPython + if sys.byteorder == "big": + assert enc == "\x00\x00\x00a" + else: + assert enc == "a\x00\x00\x00" def test_unicode_internal_decode(self): import sys Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Mon Feb 9 17:03:45 2009 @@ -24,7 +24,7 @@ 'b' : ffi_type_schar, 'B' : ffi_type_uchar, 'h' : ffi_type_sshort, - 'u' : ffi_type_uint, # XXX think deeper how to map it properly + 'u' : cast_type_to_ffitype(lltype.UniChar), 'H' : ffi_type_ushort, 'i' : cast_type_to_ffitype(rffi.INT), 'I' : cast_type_to_ffitype(rffi.UINT), Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Mon Feb 9 17:03:45 2009 @@ -160,7 +160,7 @@ def setup_class(cls): from pypy.rlib.libffi import libc_name - space = gettestobjspace(usemodules=('_rawffi','struct')) + space = gettestobjspace(usemodules=('_rawffi', 'struct')) cls.space = space cls.w_lib_name = space.wrap(cls.prepare_c_example()) cls.w_libc_name = space.wrap(libc_name) Modified: pypy/trunk/pypy/module/sys/__init__.py ============================================================================== --- pypy/trunk/pypy/module/sys/__init__.py (original) +++ pypy/trunk/pypy/module/sys/__init__.py Mon Feb 9 17:03:45 2009 @@ -1,5 +1,5 @@ from pypy.interpreter.mixedmodule import MixedModule -from pypy.interpreter.error import OperationError +from pypy.interpreter.error import OperationError class Module(MixedModule): """Sys Builtin Module. """ @@ -18,7 +18,7 @@ 'platform' : 'space.wrap(sys.platform)', 'maxint' : 'space.wrap(sys.maxint)', 'byteorder' : 'space.wrap(sys.byteorder)', - 'maxunicode' : 'space.wrap(sys.maxunicode)', + 'maxunicode' : 'space.wrap(vm.MAXUNICODE)', 'maxint' : 'space.wrap(sys.maxint)', 'stdin' : 'state.getio(space).w_stdin', '__stdin__' : 'state.getio(space).w_stdin', Modified: pypy/trunk/pypy/module/sys/vm.py ============================================================================== --- pypy/trunk/pypy/module/sys/vm.py (original) +++ pypy/trunk/pypy/module/sys/vm.py Mon Feb 9 17:03:45 2009 @@ -3,6 +3,7 @@ """ from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import ObjSpace +from pypy.rlib.runicode import MAXUNICODE import sys # ____________________________________________________________ Modified: pypy/trunk/pypy/module/unicodedata/interp_ucd.py ============================================================================== --- pypy/trunk/pypy/module/unicodedata/interp_ucd.py (original) +++ pypy/trunk/pypy/module/unicodedata/interp_ucd.py Mon Feb 9 17:03:45 2009 @@ -21,11 +21,9 @@ SCount = (LCount*NCount) def unichr_to_code_w(space, w_unichr): - if not space.is_true(space.isinstance(w_unichr, space.w_unicode)): - raise OperationError(space.w_TypeError, space.wrap('argument 1 must be unicode')) - if not space.int_w(space.len(w_unichr)) == 1: - raise OperationError(space.w_TypeError, space.wrap('need a single Unicode character as parameter')) - return space.int_w(space.ord(w_unichr)) + from pypy.rlib.runicode import ORD + u = space.unicode_w(w_unichr) + return ORD(u) class UCD(Wrappable): def __init__(self, unicodedb): Modified: pypy/trunk/pypy/rlib/libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/libffi.py (original) +++ pypy/trunk/pypy/rlib/libffi.py Mon Feb 9 17:03:45 2009 @@ -162,13 +162,15 @@ def _signed_type_for(TYPE): sz = rffi.sizeof(TYPE) - if sz == 4: return ffi_type_sint32 + if sz == 2: return ffi_type_sint16 + elif sz == 4: return ffi_type_sint32 elif sz == 8: return ffi_type_sint64 else: raise ValueError("unsupported type size for %r" % (TYPE,)) def _unsigned_type_for(TYPE): sz = rffi.sizeof(TYPE) - if sz == 4: return ffi_type_uint32 + if sz == 2: return ffi_type_uint16 + elif sz == 4: return ffi_type_uint32 elif sz == 8: return ffi_type_uint64 else: raise ValueError("unsupported type size for %r" % (TYPE,)) @@ -187,7 +189,8 @@ rffi.LONG : _signed_type_for(rffi.LONG), rffi.ULONGLONG : _unsigned_type_for(rffi.ULONGLONG), rffi.LONGLONG : _signed_type_for(rffi.LONGLONG), - lltype.Void : ffi_type_void, + lltype.Void : ffi_type_void, + lltype.UniChar : _unsigned_type_for(lltype.UniChar), } def external(name, args, result, **kwds): Modified: pypy/trunk/pypy/rlib/rsre/rsre_char.py ============================================================================== --- pypy/trunk/pypy/rlib/rsre/rsre_char.py (original) +++ pypy/trunk/pypy/rlib/rsre/rsre_char.py Mon Feb 9 17:03:45 2009 @@ -24,7 +24,8 @@ # we only see re bytecodes as Python longs, we shouldn't have to care about the # codesize. But sre_compile will compile some stuff differently depending on the # codesize (e.g., charsets). -if sys.maxunicode == 65535: +from rlib.runicode import MAXUNICODE +if MAXUNICODE == 65535: CODESIZE = 2 else: CODESIZE = 4 Modified: pypy/trunk/pypy/rlib/rstruct/unichar.py ============================================================================== --- pypy/trunk/pypy/rlib/rstruct/unichar.py (original) +++ pypy/trunk/pypy/rlib/rstruct/unichar.py Mon Feb 9 17:03:45 2009 @@ -3,10 +3,9 @@ """ import sys +from pypy.rlib.runicode import MAXUNICODE -# XXX For now we assume CPython's own native maxunicode - -if sys.maxunicode <= 65535: +if MAXUNICODE <= 65535: UNICODE_SIZE = 2 else: UNICODE_SIZE = 4 Modified: pypy/trunk/pypy/rlib/runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/runicode.py (original) +++ pypy/trunk/pypy/rlib/runicode.py Mon Feb 9 17:03:45 2009 @@ -1,9 +1,45 @@ import sys from pypy.lang.smalltalk.tool.bitmanipulation import splitter +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rlib.objectmodel import we_are_translated -MAXUNICODE = sys.maxunicode +if rffi.sizeof(lltype.UniChar) == 4: + MAXUNICODE = 0x10ffff +else: + MAXUNICODE = 0xffff BYTEORDER = sys.byteorder +if MAXUNICODE > sys.maxunicode: + # A version of unichr which allows codes outside the BMP + # even on narrow unicode builds. + # It will be used when interpreting code on top of a UCS2 CPython, + # when sizeof(wchar_t) == 4. + # Note that Python3 uses a similar implementation. + def UNICHR(c): + if we_are_translated(): + return unichr(c) + else: + if c < sys.maxunicode or c > MAXUNICODE: + return unichr(c) + else: + c -= 0x10000 + return (unichr(0xD800 + (c >> 10)) + + unichr(0xDC00 + (c & 0x03FF))) + + def ORD(u): + if we_are_translated(): + return ord(u) + else: + if isinstance(u, unicode) and len(u) == 2: + ch1 = ord(u[0]) + ch2 = ord(u[1]) + if 0xD800 <= ch1 <= 0xDBFF and 0xDC00 <= ch2 <= 0xDFFF: + return (((ch1 - 0xD800) << 10) | (ch2 - 0xDC00)) + 0x10000 + return ord(u) +else: + UNICHR = unichr + ORD = ord + def raise_unicode_exception_decode(errors, encoding, msg, s, startingpos, endingpos): @@ -143,7 +179,7 @@ else: # convert to UTF-16 if necessary if c < MAXUNICODE: - result.append(unichr(c)) + result.append(UNICHR(c)) else: # compute and append the two surrogates: # translate from 10000..10FFFF to 0..FFFF @@ -267,7 +303,7 @@ result.append(unichr(ch)) result.append(unichr(ch2)) else: - result.append(unichr((((ch & 0x3FF)<<10) | + result.append(UNICHR((((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000)) continue else: Modified: pypy/trunk/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_runicode.py (original) +++ pypy/trunk/pypy/rlib/test/test_runicode.py Mon Feb 9 17:03:45 2009 @@ -192,3 +192,13 @@ return s1 == s2 res = interpret(f, [2]) assert res + + def test_surrogates(self): + from pypy.rpython.test.test_llinterp import interpret + def f(x): + u = runicode.UNICHR(x) + t = runicode.ORD(u) + return t + + res = interpret(f, [0x10140]) + assert res == 0x10140 Modified: pypy/trunk/pypy/rpython/rint.py ============================================================================== --- pypy/trunk/pypy/rpython/rint.py (original) +++ pypy/trunk/pypy/rpython/rint.py Mon Feb 9 17:03:45 2009 @@ -419,7 +419,8 @@ raise ValueError def ll_check_unichr(n): - if 0 <= n <= sys.maxunicode: + from pypy.rlib.runicode import MAXUNICODE + if 0 <= n <= MAXUNICODE: return else: raise ValueError From afa at codespeak.net Mon Feb 9 17:28:04 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 17:28:04 +0100 (CET) Subject: [pypy-svn] r61665 - pypy/trunk/pypy/rlib/test Message-ID: <20090209162804.8D58A16A11A@codespeak.net> Author: afa Date: Mon Feb 9 17:28:01 2009 New Revision: 61665 Modified: pypy/trunk/pypy/rlib/test/test_libffi.py Log: Add a test Modified: pypy/trunk/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_libffi.py (original) +++ pypy/trunk/pypy/rlib/test/test_libffi.py Mon Feb 9 17:28:01 2009 @@ -98,6 +98,14 @@ lltype.free(z, flavor='raw') # allocation check makes no sense, since we've got GcStructs around + def test_unichar(self): + from pypy.rlib.runicode import MAXUNICODE + wchar = cast_type_to_ffitype(lltype.UniChar) + if MAXUNICODE > 65535: + assert wchar is ffi_type_uint32 + else: + assert wchar is ffi_type_uint16 + def test_call_time(self): libc = self.get_libc() # XXX assume time_t is long From afa at codespeak.net Mon Feb 9 17:29:27 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 17:29:27 +0100 (CET) Subject: [pypy-svn] r61666 - pypy/trunk/pypy/rlib/test Message-ID: <20090209162927.89DAC16A11A@codespeak.net> Author: afa Date: Mon Feb 9 17:29:27 2009 New Revision: 61666 Modified: pypy/trunk/pypy/rlib/test/test_libffi.py pypy/trunk/pypy/rlib/test/test_runicode.py Log: Fix some tests on Windows Modified: pypy/trunk/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_libffi.py (original) +++ pypy/trunk/pypy/rlib/test/test_libffi.py Mon Feb 9 17:29:27 2009 @@ -45,7 +45,7 @@ def test_library_get_func(self): lib = self.get_libc() - ptr = lib.getpointer('time', [], ffi_type_void) + ptr = lib.getpointer('fopen', [], ffi_type_void) py.test.raises(KeyError, lib.getpointer, 'xxxxxxxxxxxxxxx', [], ffi_type_void) del ptr del lib @@ -86,7 +86,7 @@ libc = self.get_libc() # XXX assume time_t is long ulong = cast_type_to_ffitype(rffi.ULONG) - ctime = libc.getpointer('time', [ffi_type_pointer], ulong) + ctime = libc.getpointer('fopen', [ffi_type_pointer], ulong) x = lltype.malloc(lltype.GcStruct('xxx')) y = lltype.malloc(lltype.GcArray(rffi.LONG), 3) z = lltype.malloc(lltype.Array(rffi.LONG), 4, flavor='raw') @@ -110,7 +110,11 @@ libc = self.get_libc() # XXX assume time_t is long ulong = cast_type_to_ffitype(rffi.ULONG) - ctime = libc.getpointer('time', [ffi_type_pointer], ulong) + try: + ctime = libc.getpointer('time', [ffi_type_pointer], ulong) + except KeyError: + # This function is named differently since msvcr80 + ctime = libc.getpointer('_time32', [ffi_type_pointer], ulong) ctime.push_arg(lltype.nullptr(rffi.CArray(rffi.LONG))) t0 = ctime.call(rffi.LONG) time.sleep(2) Modified: pypy/trunk/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_runicode.py (original) +++ pypy/trunk/pypy/rlib/test/test_runicode.py Mon Feb 9 17:29:27 2009 @@ -194,6 +194,8 @@ assert res def test_surrogates(self): + if runicode.MAXUNICODE < 65536: + py.test.skip("Narrow unicode build") from pypy.rpython.test.test_llinterp import interpret def f(x): u = runicode.UNICHR(x) From afa at codespeak.net Mon Feb 9 17:52:23 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 17:52:23 +0100 (CET) Subject: [pypy-svn] r61670 - pypy/trunk/pypy/rlib/rsre Message-ID: <20090209165223.935CA169F7A@codespeak.net> Author: afa Date: Mon Feb 9 17:52:23 2009 New Revision: 61670 Modified: pypy/trunk/pypy/rlib/rsre/rsre_char.py Log: Fix import Modified: pypy/trunk/pypy/rlib/rsre/rsre_char.py ============================================================================== --- pypy/trunk/pypy/rlib/rsre/rsre_char.py (original) +++ pypy/trunk/pypy/rlib/rsre/rsre_char.py Mon Feb 9 17:52:23 2009 @@ -24,7 +24,7 @@ # we only see re bytecodes as Python longs, we shouldn't have to care about the # codesize. But sre_compile will compile some stuff differently depending on the # codesize (e.g., charsets). -from rlib.runicode import MAXUNICODE +from pypy.rlib.runicode import MAXUNICODE if MAXUNICODE == 65535: CODESIZE = 2 else: From afa at codespeak.net Mon Feb 9 17:54:18 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 17:54:18 +0100 (CET) Subject: [pypy-svn] r61671 - pypy/trunk/pypy/lib Message-ID: <20090209165418.4AF28169F81@codespeak.net> Author: afa Date: Mon Feb 9 17:54:17 2009 New Revision: 61671 Modified: pypy/trunk/pypy/lib/syslog.py Log: Don't try to configure this module on Windows Modified: pypy/trunk/pypy/lib/syslog.py ============================================================================== --- pypy/trunk/pypy/lib/syslog.py (original) +++ pypy/trunk/pypy/lib/syslog.py Mon Feb 9 17:54:17 2009 @@ -5,6 +5,10 @@ syslog facility. """ +import sys +if sys.platform == 'win32': + raise ImportError("No syslog on Windows") + from ctypes_support import standard_c_lib as libc from ctypes import c_int, c_char_p from ctypes_configure.configure import (configure, From afa at codespeak.net Mon Feb 9 19:39:18 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 19:39:18 +0100 (CET) Subject: [pypy-svn] r61676 - in pypy/trunk/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20090209183918.6FC6616A13B@codespeak.net> Author: afa Date: Mon Feb 9 19:39:16 2009 New Revision: 61676 Modified: pypy/trunk/pypy/lib/_ctypes/function.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_cfuncs.py Log: When compiling a function with the STDCALL calling convention, the function name is of the form _@ Where is the total size of arguments pushed on the stack. Have ctypes try all possible names. test_cfuncs.py now passes on Windows Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Mon Feb 9 19:39:16 2009 @@ -140,7 +140,23 @@ if self._buffer is not None: self._ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape) return self._ptr - return self.dll._handle.ptr(self.name, argshapes, resshape) + cdll = self.dll._handle + try: + return cdll.ptr(self.name, argshapes, resshape) + except AttributeError: + if self._flags_ & _rawffi.FUNCFLAG_CDECL: + raise + + # For stdcall, try mangled names: + # funcname -> _funcname@ + # where n is 0, 4, 8, 12, ..., 128 + for i in range(32): + mangled_name = "_%s@%d" % (self.name, i*4) + try: + return cdll.ptr(mangled_name, argshapes, resshape) + except AttributeError: + pass + raise @staticmethod def _guess_argtypes(args): Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_cfuncs.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_cfuncs.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_cfuncs.py Mon Feb 9 19:39:16 2009 @@ -197,4 +197,5 @@ class TestStdcallCFunctions(TestCFunctions): def setup_class(cls): + TestCFunctions.setup_class.im_func(cls) cls._dll = stdcall_dll(_ctypes_test) From afa at codespeak.net Mon Feb 9 20:36:50 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 20:36:50 +0100 (CET) Subject: [pypy-svn] r61677 - pypy/trunk/pypy/lib/app_test/ctypes_tests Message-ID: <20090209193650.6E55616A171@codespeak.net> Author: afa Date: Mon Feb 9 20:36:48 2009 New Revision: 61677 Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_checkretval.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py Log: Skip more ctypes win32-specific tests Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_checkretval.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_checkretval.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_checkretval.py Mon Feb 9 20:36:48 2009 @@ -35,6 +35,7 @@ pass else: def test_oledll(self): + py.test.skip("_check_retval_ is not supported") raises(WindowsError, oledll.oleaut32.CreateTypeLib2, 0, 0, 0) Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py Mon Feb 9 20:36:48 2009 @@ -72,6 +72,7 @@ assert c_char_p.from_param(a) is a def test_cw_strings(self): + py.test.skip("testing implementation internals") from ctypes import byref try: from ctypes import c_wchar_p From afa at codespeak.net Mon Feb 9 20:42:22 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 9 Feb 2009 20:42:22 +0100 (CET) Subject: [pypy-svn] r61678 - pypy/trunk/lib-python/modified-2.5.2/ctypes Message-ID: <20090209194222.9B5F816A15F@codespeak.net> Author: afa Date: Mon Feb 9 20:42:19 2009 New Revision: 61678 Modified: pypy/trunk/lib-python/modified-2.5.2/ctypes/__init__.py Log: Fix repr of CDLL objects: self._handle is a class, not an address! Modified: pypy/trunk/lib-python/modified-2.5.2/ctypes/__init__.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/ctypes/__init__.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/ctypes/__init__.py Mon Feb 9 20:42:19 2009 @@ -350,9 +350,9 @@ self._handle = handle def __repr__(self): - return "<%s '%s', handle %x at %x>" % \ + return "<%s '%s', handle %s at %x>" % \ (self.__class__.__name__, self._name, - (self._handle & (_sys.maxint*2 + 1)), + self._handle, id(self) & (_sys.maxint*2 + 1)) def __getattr__(self, name): From afa at codespeak.net Tue Feb 10 01:25:00 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Feb 2009 01:25:00 +0100 (CET) Subject: [pypy-svn] r61680 - in pypy/trunk/pypy: lib/_ctypes module/_rawffi rlib Message-ID: <20090210002500.8138D169F78@codespeak.net> Author: afa Date: Tue Feb 10 01:24:57 2009 New Revision: 61680 Modified: pypy/trunk/pypy/lib/_ctypes/function.py pypy/trunk/pypy/module/_rawffi/interp_rawffi.py pypy/trunk/pypy/rlib/libffi.py Log: Really use the _FuncPtr._flags_ attribute, and pass it to the libffi layer. More win32 tests pass Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Tue Feb 10 01:24:57 2009 @@ -23,6 +23,7 @@ _argtypes_ = None _restype_ = None + _flags_ = 0 _ffiargshape = 'P' _ffishape = 'P' _fficompositesize = None @@ -60,13 +61,18 @@ restype = 'O' # void return argtypes, restype - def __init__(self, argument=None): + def __init__(self, *args): self.name = None self._objects = {keepalive_key(0):self} self._needs_free = True + argument = None + if len(args) == 1: + argument = args[0] + if isinstance(argument, (int, long)): ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) - self._ptr = _rawffi.FuncPtr(argument, ffiargs, ffires) + self._ptr = _rawffi.FuncPtr(argument, ffiargs, ffires, + self._flags_) self._buffer = self._ptr.byptr() elif callable(argument): self.callable = argument @@ -83,7 +89,8 @@ # we need to check dll anyway ptr = self._getfuncptr([], ctypes.c_int) self._buffer = ptr.byptr() - elif argument is None: + + elif len(args) == 0: # this is needed for casts self._buffer = _rawffi.Array('P')(1) return @@ -138,11 +145,13 @@ argshapes = [arg._ffiargshape for arg in argtypes] resshape = restype._ffiargshape if self._buffer is not None: - self._ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape) + self._ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape, + self._flags_) return self._ptr + cdll = self.dll._handle try: - return cdll.ptr(self.name, argshapes, resshape) + return cdll.ptr(self.name, argshapes, resshape, self._flags_) except AttributeError: if self._flags_ & _rawffi.FUNCFLAG_CDECL: raise @@ -153,7 +162,8 @@ for i in range(32): mangled_name = "_%s@%d" % (self.name, i*4) try: - return cdll.ptr(mangled_name, argshapes, resshape) + return cdll.ptr(mangled_name, argshapes, resshape, + self._flags_) except AttributeError: pass raise Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Tue Feb 10 01:24:57 2009 @@ -142,7 +142,7 @@ self.w_cache = space.newdict() self.space = space - def ptr(self, space, name, w_argtypes, w_restype): + def ptr(self, space, name, w_argtypes, w_restype, flags=0): """ Get a pointer for function name with provided argtypes and restype """ @@ -160,14 +160,15 @@ raise ffi_argtypes, argletters = unpack_argshapes(space, w_argtypes) try: - ptr = self.cdll.getrawpointer(name, ffi_argtypes, ffi_restype) + ptr = self.cdll.getrawpointer(name, ffi_argtypes, ffi_restype, + flags) w_funcptr = W_FuncPtr(space, ptr, argletters, resshape) space.setitem(self.w_cache, w_key, w_funcptr) return w_funcptr except KeyError: raise OperationError(space.w_AttributeError, space.wrap( "No symbol %s found in library %s" % (name, self.name))) - ptr.unwrap_spec = ['self', ObjSpace, str, W_Root, W_Root] + ptr.unwrap_spec = ['self', ObjSpace, str, W_Root, W_Root, int] def getaddressindll(self, space, name): try: @@ -411,12 +412,13 @@ return space.w_None call.unwrap_spec = ['self', ObjSpace, 'args_w'] -def descr_new_funcptr(space, w_tp, addr, w_args, w_res): +def descr_new_funcptr(space, w_tp, addr, w_args, w_res, flags=0): ffi_args, args = unpack_argshapes(space, w_args) ffi_res, res = unpack_resshape(space, w_res) - ptr = RawFuncPtr('???', ffi_args, ffi_res, rffi.cast(rffi.VOIDP, addr)) + ptr = RawFuncPtr('???', ffi_args, ffi_res, rffi.cast(rffi.VOIDP, addr), + flags) return space.wrap(W_FuncPtr(space, ptr, args, res)) -descr_new_funcptr.unwrap_spec = [ObjSpace, W_Root, r_uint, W_Root, W_Root] +descr_new_funcptr.unwrap_spec = [ObjSpace, W_Root, r_uint, W_Root, W_Root, int] W_FuncPtr.typedef = TypeDef( 'FuncPtr', Modified: pypy/trunk/pypy/rlib/libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/libffi.py (original) +++ pypy/trunk/pypy/rlib/libffi.py Tue Feb 10 01:24:57 2009 @@ -549,8 +549,6 @@ AbstractFuncPtr.__del__(self) class CDLL: - flags = FUNCFLAG_CDECL - def __init__(self, libname, unload_on_finalization=True): self.unload_on_finalization = unload_on_finalization self.lib = lltype.nullptr(rffi.CCHARP.TO) @@ -563,17 +561,17 @@ dlclose(self.lib) self.lib = lltype.nullptr(rffi.CCHARP.TO) - def getpointer(self, name, argtypes, restype): + def getpointer(self, name, argtypes, restype, flags): # these arguments are already casted to proper ffi # structures! return FuncPtr(name, argtypes, restype, dlsym(self.lib, name), - flags=self.flags) + flags=flags) - def getrawpointer(self, name, argtypes, restype): + def getrawpointer(self, name, argtypes, restype, flags): # these arguments are already casted to proper ffi # structures! return RawFuncPtr(name, argtypes, restype, dlsym(self.lib, name), - flags=self.flags) + flags=flags) def getaddressindll(self, name): return dlsym(self.lib, name) From afa at codespeak.net Tue Feb 10 01:41:02 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Feb 2009 01:41:02 +0100 (CET) Subject: [pypy-svn] r61681 - in pypy/trunk/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20090210004102.8867616A164@codespeak.net> Author: afa Date: Tue Feb 10 01:40:59 2009 New Revision: 61681 Modified: pypy/trunk/pypy/lib/_ctypes/function.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_guess_argtypes.py Log: When guessing argument types, a unicode string should be converted to a c_wchar_p buffer. This matches CPython behavior. Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Tue Feb 10 01:40:59 2009 @@ -171,13 +171,16 @@ @staticmethod def _guess_argtypes(args): from _ctypes import _CData - from ctypes import c_char_p, c_void_p, c_int, Array, Structure + from ctypes import c_char_p, c_wchar_p, c_void_p, c_int + from ctypes import Array, Structure res = [] for arg in args: if hasattr(arg, '_as_parameter_'): arg = arg._as_parameter_ - if isinstance(arg, basestring): + if isinstance(arg, str): res.append(c_char_p) + elif isinstance(arg, unicode): + res.append(c_wchar_p) elif isinstance(arg, _CData): res.append(type(arg)) elif arg is None: Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_guess_argtypes.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_guess_argtypes.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_guess_argtypes.py Tue Feb 10 01:40:59 2009 @@ -18,7 +18,7 @@ assert guess(['xca']) == [c_char_p] assert guess([None]) == [c_void_p] assert guess([c_int(3)]) == [c_int] - assert guess([u'xca']) == [c_char_p] + assert guess([u'xca']) == [c_wchar_p] class Stuff: pass @@ -27,4 +27,8 @@ assert guess([s]) == [c_void_p] - # not sure what else.... +def test_guess_unicode(): + dll = ctypes.CDLL(str(conftest.sofile)) + wcslen = dll.my_wcslen + text = u"Some long unicode string" + assert ctypes.cdll.msvcrt.wcslen(text) == len(text) From arigo at codespeak.net Tue Feb 10 12:30:35 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Feb 2009 12:30:35 +0100 (CET) Subject: [pypy-svn] r61682 - in pypy/trunk/pypy: rlib rpython rpython/lltypesystem Message-ID: <20090210113035.3DF1116A001@codespeak.net> Author: arigo Date: Tue Feb 10 12:30:33 2009 New Revision: 61682 Modified: pypy/trunk/pypy/rlib/debug.py pypy/trunk/pypy/rlib/jit.py pypy/trunk/pypy/rlib/objectmodel.py pypy/trunk/pypy/rpython/llinterp.py pypy/trunk/pypy/rpython/lltypesystem/lloperation.py pypy/trunk/pypy/rpython/lltypesystem/rstr.py Log: (fijal, arigo) Port small bits from the 'oo-jit' branch, as needed by the pyjitpl5. Modified: pypy/trunk/pypy/rlib/debug.py ============================================================================== --- pypy/trunk/pypy/rlib/debug.py (original) +++ pypy/trunk/pypy/rlib/debug.py Tue Feb 10 12:30:33 2009 @@ -16,9 +16,27 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype vlist = hop.inputargs(lltype.Bool, lltype.Void) + hop.exception_cannot_occur() hop.genop('debug_assert', vlist) +def debug_print(*args): + for arg in args: + print >> sys.stderr, arg, + print >> sys.stderr + +class Entry(ExtRegistryEntry): + _about_ = debug_print + + def compute_result_annotation(self, *args_s): + return None + + def specialize_call(self, hop): + vlist = hop.inputargs(*hop.args_r) + hop.exception_cannot_occur() + hop.genop('debug_print', vlist) + + def llinterpcall(RESTYPE, pythonfunction, *args): """When running on the llinterp, this causes the llinterp to call to the provided Python function with the run-time value of the given args. Modified: pypy/trunk/pypy/rlib/jit.py ============================================================================== --- pypy/trunk/pypy/rlib/jit.py (original) +++ pypy/trunk/pypy/rlib/jit.py Tue Feb 10 12:30:33 2009 @@ -1,5 +1,6 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rlib.objectmodel import CDefinedIntSymbolic +from pypy.rlib.unroll import unrolling_iterable def purefunction(func): func._pure_function_ = True @@ -14,18 +15,6 @@ def compute_result_annotation(self, s_x, **kwds_s): from pypy.annotation import model as annmodel s_x = annmodel.not_const(s_x) - if 's_access_directly' in kwds_s: - if isinstance(s_x, annmodel.SomeInstance): - from pypy.objspace.flow.model import Constant - classdesc = s_x.classdef.classdesc - virtualizable = classdesc.read_attribute('_virtualizable_', - Constant(False)).value - if virtualizable: - flags = s_x.flags.copy() - flags['access_directly'] = True - s_x = annmodel.SomeInstance(s_x.classdef, - s_x.can_be_None, - flags) return s_x def specialize_call(self, hop, **kwds_i): @@ -83,5 +72,232 @@ v, = hop.inputargs(hop.args_r[0]) return hop.genop('is_early_constant', [v], resulttype=lltype.Bool) +# ____________________________________________________________ +# User interface for the hotpath JIT policy +class JitHintError(Exception): + """Inconsistency in the JIT hints.""" +PARAMETERS = {'threshold': 40, + 'trace_eagerness': 10, + 'hash_bits': 14, + } +unroll_parameters = unrolling_iterable(PARAMETERS.keys()) + +class JitDriver: + """Base class to declare fine-grained user control on the JIT. So + far, there must be a singleton instance of JitDriver. This style + will allow us (later) to support a single RPython program with + several independent JITting interpreters in it. + """ + def __init__(self, greens=None, reds=None): + if greens is not None: + self.greens = greens + if reds is not None: + self.reds = reds + if not hasattr(self, 'greens') or not hasattr(self, 'reds'): + raise AttributeError("no 'greens' or 'reds' supplied") + self._alllivevars = dict.fromkeys(self.greens + self.reds) + self._params = PARAMETERS.copy() + if hasattr(self, 'on_enter_jit'): + self._make_on_enter_jit_wrappers() + self._make_extregistryentries() + + def _freeze_(self): + return True + + def jit_merge_point(self, **livevars): + # special-cased by ExtRegistryEntry + assert dict.fromkeys(livevars) == self._alllivevars + + def can_enter_jit(self, **livevars): + # special-cased by ExtRegistryEntry + assert dict.fromkeys(livevars) == self._alllivevars + + def _set_param(self, name, value): + # special-cased by ExtRegistryEntry + # (internal, must receive a constant 'name') + assert name in PARAMETERS + self._params[name] = value + + def set_param(self, name, value): + """Set one of the tunable JIT parameter.""" + for name1 in unroll_parameters: + if name1 == name: + self._set_param(name1, value) + return + raise ValueError("no such parameter") + set_param._annspecialcase_ = 'specialize:arg(0)' + + def set_user_param(self, text): + """Set the tunable JIT parameters from a user-supplied string + following the format 'param=value,param=value'. For programmatic + setting of parameters, use directly JitDriver.set_param(). + """ + for s in text.split(','): + s = s.strip(' ') + parts = s.split('=') + if len(parts) != 2: + raise ValueError + try: + value = int(parts[1]) + except ValueError: + raise # re-raise the ValueError (annotator hint) + name = parts[0] + self.set_param(name, value) + set_user_param._annspecialcase_ = 'specialize:arg(0)' + + def compute_invariants(self, reds, *greens): + """This can compute a value or tuple that is passed as a green + argument 'invariants' to on_enter_jit(). It should in theory + only depend on the 'greens', but in practice it can peek at the + reds currently stored in 'self'. This allows the extraction in + an interpreter-specific way of whatever red information that + ultimately depends on the greens only. + """ + compute_invariants._annspecialcase_ = 'specialize:arg(0)' + + def _emulate_method_calls(self, bk, livevars_s): + # annotate "self.on_enter_jit()" if it is defined. + # self.on_enter_jit(invariants, reds, *greenvars) is called with a + # copy of the value of the red variables in 'reds'. The red variables + # can be modified in order to give hints to the JIT about the + # redboxes. + from pypy.annotation import model as annmodel + if hasattr(self, 'on_enter_jit'): + args_s = [] + for name in self.greens + self.reds: + args_s.append(livevars_s['s_' + name]) + + key = "rlib.jit.JitDriver._on_enter_jit" + s_func = bk.immutablevalue(self._on_enter_jit_wrapper) + s_result = bk.emulate_pbc_call(key, s_func, args_s) + assert annmodel.s_None.contains(s_result) + + key = "rlib.jit.JitDriver._compute_invariants" + s_func = bk.immutablevalue(self._compute_invariants_wrapper) + bk.emulate_pbc_call(key, s_func, args_s) + + def _make_on_enter_jit_wrappers(self): + # build some unrolling wrappers around on_enter_jit() and + # compute_invariants() which takes all green and red arguments + # and puts the red ones in a fresh instance of the + # RedVarsHolder. This logic is here in jit.py because it needs + # to be annotated and rtyped as a high-level function. + + num_green_args = len(self.greens) + unroll_reds = unrolling_iterable(self.reds) + + class RedVarsHolder: + def __init__(self, *redargs): + i = 0 + for name in unroll_reds: + setattr(self, name, redargs[i]) + i += 1 + + self._RedVarsHolder = RedVarsHolder + + def _on_enter_jit_wrapper(*allargs): + # This is what theoretically occurs when we are entering the + # JIT. In truth, compute_invariants() is called only once + # per set of greens and its result is cached. On the other + # hand, on_enter_jit() is compiled into machine code and so + # it runs every time the execution jumps from the regular + # interpreter to the machine code. Also note that changes + # to the attribute of RedVarsHolder are reflected back in + # the caller. + reds = RedVarsHolder(*allargs[num_green_args:]) + greens = allargs[:num_green_args] + invariants = self.compute_invariants(reds, *greens) + return self.on_enter_jit(invariants, reds, *greens) + self._on_enter_jit_wrapper = _on_enter_jit_wrapper + + def _compute_invariants_wrapper(*allargs): + reds = RedVarsHolder(*allargs[num_green_args:]) + greens = allargs[:num_green_args] + return self.compute_invariants(reds, *greens) + self._compute_invariants_wrapper = _compute_invariants_wrapper + + def _make_extregistryentries(self): + # workaround: we cannot declare ExtRegistryEntries for functions + # used as methods of a frozen object, but we can attach the + # bound methods back to 'self' and make ExtRegistryEntries + # specifically for them. + self.jit_merge_point = self.jit_merge_point + self.can_enter_jit = self.can_enter_jit + self._set_param = self._set_param + + class Entry(ExtEnterLeaveMarker): + _about_ = (self.jit_merge_point, self.can_enter_jit) + + class Entry(ExtSetParam): + _about_ = self._set_param + +# ____________________________________________________________ +# +# Annotation and rtyping of some of the JitDriver methods + +class ExtEnterLeaveMarker(ExtRegistryEntry): + # Replace a call to myjitdriver.jit_merge_point(**livevars) + # with an operation jit_marker('jit_merge_point', myjitdriver, livevars...) + # Also works with can_enter_jit. + + def compute_result_annotation(self, **kwds_s): + from pypy.annotation import model as annmodel + driver = self.instance.im_self + keys = kwds_s.keys() + keys.sort() + expected = ['s_' + name for name in driver.greens + driver.reds] + expected.sort() + if keys != expected: + raise JitHintError("%s expects the following keyword " + "arguments: %s" % (self.instance, + expected)) + driver._emulate_method_calls(self.bookkeeper, kwds_s) + return annmodel.s_None + + def specialize_call(self, hop, **kwds_i): + # XXX to be complete, this could also check that the concretetype + # of the variables are the same for each of the calls. + from pypy.rpython.error import TyperError + from pypy.rpython.lltypesystem import lltype + driver = self.instance.im_self + greens_v = [] + reds_v = [] + for name in driver.greens: + i = kwds_i['i_' + name] + r_green = hop.args_r[i] + v_green = hop.inputarg(r_green, arg=i) + greens_v.append(v_green) + for name in driver.reds: + i = kwds_i['i_' + name] + r_red = hop.args_r[i] + v_red = hop.inputarg(r_red, arg=i) + reds_v.append(v_red) + hop.exception_cannot_occur() + vlist = [hop.inputconst(lltype.Void, self.instance.__name__), + hop.inputconst(lltype.Void, driver)] + vlist.extend(greens_v) + vlist.extend(reds_v) + return hop.genop('jit_marker', vlist, + resulttype=lltype.Void) + +class ExtSetParam(ExtRegistryEntry): + + def compute_result_annotation(self, s_name, s_value): + from pypy.annotation import model as annmodel + assert s_name.is_constant() + assert annmodel.SomeInteger().contains(s_value) + return annmodel.s_None + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + driver = self.instance.im_self + name = hop.args_s[0].const + v_value = hop.inputarg(lltype.Signed, arg=1) + vlist = [hop.inputconst(lltype.Void, "set_param"), + hop.inputconst(lltype.Void, driver), + hop.inputconst(lltype.Void, name), + v_value] + return hop.genop('jit_marker', vlist, + resulttype=lltype.Void) Modified: pypy/trunk/pypy/rlib/objectmodel.py ============================================================================== --- pypy/trunk/pypy/rlib/objectmodel.py (original) +++ pypy/trunk/pypy/rlib/objectmodel.py Tue Feb 10 12:30:33 2009 @@ -286,6 +286,9 @@ def get(self, key, default): return self._dict.get(_r_dictkey(self, key), default) + def setdefault(self, key, default): + return self._dict.setdefault(_r_dictkey(self, key), default) + def copy(self): result = r_dict(self.key_eq, self.key_hash) result.update(self) Modified: pypy/trunk/pypy/rpython/llinterp.py ============================================================================== --- pypy/trunk/pypy/rpython/llinterp.py (original) +++ pypy/trunk/pypy/rpython/llinterp.py Tue Feb 10 12:30:33 2009 @@ -76,6 +76,8 @@ self.tracer.dump('LLException: %s\n' % (e,)) raise except Exception, e: + if getattr(e, '_go_through_llinterp_uncaught_', False): + raise log.error("AN ERROR OCCURED: %s" % (e, )) self.print_traceback() if self.tracer: @@ -423,6 +425,18 @@ if exc is None: original = sys.exc_info() exc = original[1] + # it makes no sense to convert some exception classes that + # just mean something buggy crashed + if isinstance(exc, (AssertionError, AttributeError, + TypeError, NameError, + KeyboardInterrupt, SystemExit, + ImportError, SyntaxError)): + raise original[0], original[1], original[2] # re-raise it + # for testing the JIT (see ContinueRunningNormally) we need + # to let some exceptions introduced by the JIT go through + # the llinterpreter uncaught + if getattr(exc, '_go_through_llinterp_uncaught_', False): + raise original[0], original[1], original[2] # re-raise it extraargs = (original,) else: extraargs = () @@ -445,6 +459,8 @@ except LLException, e: raise except Exception, e: + if getattr(e, '_go_through_llinterp_uncaught_', False): + raise if getattr(obj, '_debugexc', False): log.ERROR('The llinterpreter got an ' 'unexpected exception when calling') @@ -513,6 +529,9 @@ def op_debug_llinterpcall(self, pythonfunction, *args_ll): return pythonfunction(*args_ll) + def op_jit_marker(self, *args): + pass + def op_instrument_count(self, ll_tag, ll_label): pass # xxx for now Modified: pypy/trunk/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/lloperation.py Tue Feb 10 12:30:33 2009 @@ -390,6 +390,7 @@ # __________ used by the JIT ________ 'call_boehm_gc_alloc': LLOp(canraise=(MemoryError,)), + 'jit_marker': LLOp(), # __________ GC operations __________ Modified: pypy/trunk/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rstr.py Tue Feb 10 12:30:33 2009 @@ -55,14 +55,16 @@ llmemory.itemoffsetof(TP.chars, 0) + llmemory.sizeof(CHAR_TP) * item) - def copy_string_contents(s1, s2, s1start, s2start, lgt): - assert s1start >= 0 - assert s2start >= 0 - assert lgt >= 0 - src = llmemory.cast_ptr_to_adr(s1) + _str_ofs(s1start) - dest = llmemory.cast_ptr_to_adr(s2) + _str_ofs(s2start) - llmemory.raw_memcopy(src, dest, llmemory.sizeof(CHAR_TP) * lgt) + def copy_string_contents(src, dst, srcstart, dststart, length): + assert srcstart >= 0 + assert dststart >= 0 + assert length >= 0 + src = llmemory.cast_ptr_to_adr(src) + _str_ofs(srcstart) + dst = llmemory.cast_ptr_to_adr(dst) + _str_ofs(dststart) + llmemory.raw_memcopy(src, dst, llmemory.sizeof(CHAR_TP) * length) copy_string_contents._always_inline_ = True + copy_string_contents.oopspec = ( + '%s.copy_contents(src, dst, srcstart, dststart, length)' % name) return func_with_new_name(copy_string_contents, 'copy_%s_contents' % name) copy_string_contents = _new_copy_contents_fun(STR, Char, 'string') From arigo at codespeak.net Tue Feb 10 12:51:01 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Feb 2009 12:51:01 +0100 (CET) Subject: [pypy-svn] r61684 - in pypy/trunk/pypy/rpython: . test Message-ID: <20090210115101.7FF6F16A11A@codespeak.net> Author: arigo Date: Tue Feb 10 12:50:59 2009 New Revision: 61684 Modified: pypy/trunk/pypy/rpython/rlist.py pypy/trunk/pypy/rpython/test/test_rlist.py Log: (fijal, arigo) For getitem on lists that are not mutable, create a special function to do it -- basically just by calling the old function, but with a different oopspec, 'list.getitem_foldable()'. Useful for pyjitpl5. Modified: pypy/trunk/pypy/rpython/rlist.py ============================================================================== --- pypy/trunk/pypy/rpython/rlist.py (original) +++ pypy/trunk/pypy/rpython/rlist.py Tue Feb 10 12:50:59 2009 @@ -224,10 +224,16 @@ spec = dum_nocheck v_func = hop.inputconst(Void, spec) v_lst, v_index = hop.inputargs(r_lst, Signed) - if hop.args_s[1].nonneg: - llfn = ll_getitem_nonneg + if hop.args_s[0].listdef.listitem.mutated: + if hop.args_s[1].nonneg: + llfn = ll_getitem_nonneg + else: + llfn = ll_getitem else: - llfn = ll_getitem + if hop.args_s[1].nonneg: + llfn = ll_getitem_foldable_nonneg + else: + llfn = ll_getitem_foldable if checkidx: hop.exception_is_here() else: @@ -668,6 +674,19 @@ ll_getitem.oopargcheck = lambda l, index: (bool(l) and -l.ll_length() <= index < l.ll_length()) +def ll_getitem_foldable_nonneg(func, l, index): + return ll_getitem_nonneg(func, l, index) +ll_getitem_foldable_nonneg.oopspec = 'list.getitem_foldable(l, index)' +ll_getitem_foldable_nonneg.oopargcheck = lambda l, index: (bool(l) and + 0 <= index < l.ll_length()) + +def ll_getitem_foldable(func, l, index): + return ll_getitem(func, l, index) +ll_getitem_foldable.oopspec = 'list.getitem_foldable(l, index)' +ll_getitem_foldable.oopargcheck = lambda l, index: (bool(l) + and -l.ll_length() <= + index < l.ll_length()) + def ll_setitem_nonneg(func, l, index, newitem): ll_assert(index >= 0, "unexpectedly negative list setitem index") if func is dum_checkidx: Modified: pypy/trunk/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_rlist.py (original) +++ pypy/trunk/pypy/rpython/test/test_rlist.py Tue Feb 10 12:50:59 2009 @@ -1383,5 +1383,20 @@ lis = self.interpret(fnpop, [i]) assert list_is_clear(lis, 3-i) + def test_oopspec(self): + lst1 = [123, 456] # non-mutated list + def f(i): + lst2 = [i] + lst2.append(42) # mutated list + return lst1[i] + lst2[i] + _, _, graph = self.gengraph(f, [int]) + block = graph.startblock + lst1_getitem_op = block.operations[-3] # XXX graph fishing + lst2_getitem_op = block.operations[-2] + func1 = lst1_getitem_op.args[0].value._obj._callable + func2 = lst2_getitem_op.args[0].value._obj._callable + assert func1.oopspec == 'list.getitem_foldable(l, index)' + assert func2.oopspec == 'list.getitem(l, index)' + class TestOOtype(BaseTestRlist, OORtypeMixin): rlist = oo_rlist From arigo at codespeak.net Tue Feb 10 13:02:26 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Feb 2009 13:02:26 +0100 (CET) Subject: [pypy-svn] r61685 - pypy/trunk/pypy/rpython Message-ID: <20090210120226.48F34169EF0@codespeak.net> Author: arigo Date: Tue Feb 10 13:02:25 2009 New Revision: 61685 Modified: pypy/trunk/pypy/rpython/rlist.py Log: (fijal, arigo) Two more functions that need a constant-foldable version. Modified: pypy/trunk/pypy/rpython/rlist.py ============================================================================== --- pypy/trunk/pypy/rpython/rlist.py (original) +++ pypy/trunk/pypy/rpython/rlist.py Tue Feb 10 13:02:25 2009 @@ -117,11 +117,19 @@ def rtype_len(self, hop): v_lst, = hop.inputargs(self) - return hop.gendirectcall(ll_len, v_lst) + if hop.args_s[0].listdef.listitem.resized: + ll_func = ll_len + else: + ll_func = ll_len_foldable + return hop.gendirectcall(ll_func, v_lst) def rtype_is_true(self, hop): v_lst, = hop.inputargs(self) - return hop.gendirectcall(ll_list_is_true, v_lst) + if hop.args_s[0].listdef.listitem.resized: + ll_func = ll_list_is_true + else: + ll_func = ll_list_is_true_foldable + return hop.gendirectcall(ll_func, v_lst) def rtype_method_reverse(self, hop): v_lst, = hop.inputargs(self) @@ -522,6 +530,16 @@ ll_list_is_true.oopspec = 'list.nonzero(l)' ll_list_is_true.oopargcheck = lambda l: True +def ll_len_foldable(l): + return l.ll_length() +ll_len_foldable.oopspec = 'list.len_foldable(l)' +ll_len_foldable.oopargcheck = lambda l: bool(l) + +def ll_list_is_true_foldable(l): + return ll_list_is_true(l) +ll_list_is_true_foldable.oopspec = 'list.nonzero_foldable(l)' +ll_list_is_true_foldable.oopargcheck = lambda l: True + def ll_append(l, newitem): length = l.ll_length() l._ll_resize_ge(length+1) # see "a note about overflows" above From arigo at codespeak.net Tue Feb 10 14:03:57 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 10 Feb 2009 14:03:57 +0100 (CET) Subject: [pypy-svn] r61688 - pypy/trunk/pypy/rpython/lltypesystem Message-ID: <20090210130357.3981916A14A@codespeak.net> Author: arigo Date: Tue Feb 10 14:03:55 2009 New Revision: 61688 Modified: pypy/trunk/pypy/rpython/lltypesystem/rclass.py Log: (fijal, arigo) Port a hint from oo-jit. Modified: pypy/trunk/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rclass.py Tue Feb 10 14:03:55 2009 @@ -58,7 +58,8 @@ OBJECT_VTABLE = lltype.ForwardReference() CLASSTYPE = Ptr(OBJECT_VTABLE) OBJECT = GcStruct('object', ('typeptr', CLASSTYPE), - hints = {'immutable': True, 'shouldntbenull': True}) + hints = {'immutable': True, 'shouldntbenull': True, + 'typeptr': True}) OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', #('parenttypeptr', CLASSTYPE), From afa at codespeak.net Tue Feb 10 14:19:23 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Feb 2009 14:19:23 +0100 (CET) Subject: [pypy-svn] r61690 - pypy/trunk/pypy/lib/app_test/ctypes_tests Message-ID: <20090210131923.4364A16A197@codespeak.net> Author: afa Date: Tue Feb 10 14:19:22 2009 New Revision: 61690 Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_guess_argtypes.py Log: Fix this test. It segfaults on Linux, see http://bugs.python.org/issue5203 pypyp-c runs it with success :-) Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_guess_argtypes.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_guess_argtypes.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_guess_argtypes.py Tue Feb 10 14:19:22 2009 @@ -28,7 +28,10 @@ assert guess([s]) == [c_void_p] def test_guess_unicode(): - dll = ctypes.CDLL(str(conftest.sofile)) + if not hasattr(sys, 'pypy_translation_info') and sys.platform != 'win32': + py.test.skip("CPython segfaults: see http://bugs.python.org/issue5203") + import conftest + dll = CDLL(str(conftest.sofile)) wcslen = dll.my_wcslen text = u"Some long unicode string" - assert ctypes.cdll.msvcrt.wcslen(text) == len(text) + assert wcslen(text) == len(text) From afa at codespeak.net Tue Feb 10 14:22:42 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Feb 2009 14:22:42 +0100 (CET) Subject: [pypy-svn] r61691 - in pypy/trunk/pypy: module/_rawffi rlib Message-ID: <20090210132242.A495416A197@codespeak.net> Author: afa Date: Tue Feb 10 14:22:42 2009 New Revision: 61691 Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py pypy/trunk/pypy/rlib/libffi.py Log: Be sure to add a default value for 'flags' to every function of these modules Also, make FUNCFLAG_CDECL the default, since this is the default calling convention for C code. Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Tue Feb 10 14:22:42 2009 @@ -142,7 +142,7 @@ self.w_cache = space.newdict() self.space = space - def ptr(self, space, name, w_argtypes, w_restype, flags=0): + def ptr(self, space, name, w_argtypes, w_restype, flags=FUNCFLAG_CDECL): """ Get a pointer for function name with provided argtypes and restype """ @@ -412,7 +412,7 @@ return space.w_None call.unwrap_spec = ['self', ObjSpace, 'args_w'] -def descr_new_funcptr(space, w_tp, addr, w_args, w_res, flags=0): +def descr_new_funcptr(space, w_tp, addr, w_args, w_res, flags=FUNCFLAG_CDECL): ffi_args, args = unpack_argshapes(space, w_args) ffi_res, res = unpack_resshape(space, w_res) ptr = RawFuncPtr('???', ffi_args, ffi_res, rffi.cast(rffi.VOIDP, addr), Modified: pypy/trunk/pypy/rlib/libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/libffi.py (original) +++ pypy/trunk/pypy/rlib/libffi.py Tue Feb 10 14:22:42 2009 @@ -386,7 +386,7 @@ ll_cif = lltype.nullptr(FFI_CIFP.TO) ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) - def __init__(self, name, argtypes, restype, flags=0): + def __init__(self, name, argtypes, restype, flags=FUNCFLAG_CDECL): self.name = name self.argtypes = argtypes self.restype = restype @@ -456,7 +456,7 @@ class RawFuncPtr(AbstractFuncPtr): - def __init__(self, name, argtypes, restype, funcsym, flags=0): + def __init__(self, name, argtypes, restype, funcsym, flags=FUNCFLAG_CDECL): AbstractFuncPtr.__init__(self, name, argtypes, restype, flags) self.funcsym = funcsym @@ -476,7 +476,7 @@ ll_args = lltype.nullptr(rffi.VOIDPP.TO) ll_result = lltype.nullptr(rffi.VOIDP.TO) - def __init__(self, name, argtypes, restype, funcsym, flags=0): + def __init__(self, name, argtypes, restype, funcsym, flags=FUNCFLAG_CDECL): # initialize each one of pointers with null AbstractFuncPtr.__init__(self, name, argtypes, restype, flags) self.funcsym = funcsym @@ -561,13 +561,13 @@ dlclose(self.lib) self.lib = lltype.nullptr(rffi.CCHARP.TO) - def getpointer(self, name, argtypes, restype, flags): + def getpointer(self, name, argtypes, restype, flags=FUNCFLAG_CDECL): # these arguments are already casted to proper ffi # structures! return FuncPtr(name, argtypes, restype, dlsym(self.lib, name), flags=flags) - def getrawpointer(self, name, argtypes, restype, flags): + def getrawpointer(self, name, argtypes, restype, flags=FUNCFLAG_CDECL): # these arguments are already casted to proper ffi # structures! return RawFuncPtr(name, argtypes, restype, dlsym(self.lib, name), From afa at codespeak.net Tue Feb 10 18:05:20 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Feb 2009 18:05:20 +0100 (CET) Subject: [pypy-svn] r61701 - in pypy/trunk/pypy: module/_rawffi/test rlib/test Message-ID: <20090210170520.30E64169F3E@codespeak.net> Author: afa Date: Tue Feb 10 18:05:18 2009 New Revision: 61701 Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py pypy/trunk/pypy/rlib/test/test_libffi.py Log: Skip libffi structure tests which segfaults on x86_64 processors. On these machines, small structures (<=16 bytes) may be passed in registers if all their members are "simple enough" (no long double for example) To check this, the libffi library needs to iterate over the elements of the structure, but we never fill the 'c_elements' member :-( Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Tue Feb 10 18:05:18 2009 @@ -735,7 +735,12 @@ raises(_rawffi.SegfaultException, a.__setitem__, 3, 3) def test_struct_byvalue(self): - import _rawffi + import _rawffi, platform + if platform.machine() == 'x86_64': + skip("Segfaults on x86_64 because small structures " + "may be passed in registers and " + "c_elements must not be null") + X_Y = _rawffi.Structure([('x', 'l'), ('y', 'l')]) x_y = X_Y() lib = _rawffi.CDLL(self.lib_name) @@ -747,7 +752,12 @@ x_y.free() def test_ret_struct(self): - import _rawffi + import _rawffi, platform + if platform.machine() == 'x86_64': + skip("Segfaults on x86_64 because small structures " + "may be passed in registers and " + "c_elements must not be null") + S2H = _rawffi.Structure([('x', 'h'), ('y', 'h')]) s2h = S2H() lib = _rawffi.CDLL(self.lib_name) Modified: pypy/trunk/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_libffi.py (original) +++ pypy/trunk/pypy/rlib/test/test_libffi.py Tue Feb 10 18:05:18 2009 @@ -241,6 +241,11 @@ lltype.free(tp, flavor='raw') def test_struct_by_val(self): + import platform + if platform.machine() == 'x86_64': + py.test.skip("Segfaults on x86_64 because small structures " + "may be passed in registers and " + "c_elements must not be null") from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.platform import platform from pypy.tool.udir import udir @@ -292,6 +297,11 @@ assert not ALLOCATED def test_ret_struct_val(self): + import platform + if platform.machine() == 'x86_64': + py.test.skip("Segfaults on x86_64 because small structures " + "may be passed in registers and " + "c_elements must not be null") from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.platform import platform from pypy.tool.udir import udir From afa at codespeak.net Tue Feb 10 23:42:40 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 10 Feb 2009 23:42:40 +0100 (CET) Subject: [pypy-svn] r61702 - pypy/trunk/pypy/module/unicodedata Message-ID: <20090210224240.B351916A1A4@codespeak.net> Author: afa Date: Tue Feb 10 23:42:37 2009 New Revision: 61702 Modified: pypy/trunk/pypy/module/unicodedata/interp_ucd.py Log: Revert this change in unicodedata, because the functions did not check anymore that the string is composed of a single unicode char, and broke tests. Modified: pypy/trunk/pypy/module/unicodedata/interp_ucd.py ============================================================================== --- pypy/trunk/pypy/module/unicodedata/interp_ucd.py (original) +++ pypy/trunk/pypy/module/unicodedata/interp_ucd.py Tue Feb 10 23:42:37 2009 @@ -21,9 +21,11 @@ SCount = (LCount*NCount) def unichr_to_code_w(space, w_unichr): - from pypy.rlib.runicode import ORD - u = space.unicode_w(w_unichr) - return ORD(u) + if not space.is_true(space.isinstance(w_unichr, space.w_unicode)): + raise OperationError(space.w_TypeError, space.wrap('argument 1 must be unicode')) + if not space.int_w(space.len(w_unichr)) == 1: + raise OperationError(space.w_TypeError, space.wrap('need a single Unicode character as parameter')) + return space.int_w(space.ord(w_unichr)) class UCD(Wrappable): def __init__(self, unicodedb): From afa at codespeak.net Wed Feb 11 00:30:42 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Feb 2009 00:30:42 +0100 (CET) Subject: [pypy-svn] r61705 - in pypy/trunk/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20090210233042.E428D16A1BB@codespeak.net> Author: afa Date: Wed Feb 11 00:30:39 2009 New Revision: 61705 Modified: pypy/trunk/pypy/lib/_ctypes/structure.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_structures.py Log: ctypes Structure instances accept extra attributes, and simply store them in the __dict__. Modified: pypy/trunk/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/structure.py (original) +++ pypy/trunk/pypy/lib/_ctypes/structure.py Wed Feb 11 00:30:39 2009 @@ -181,7 +181,7 @@ try: fieldtype = self._fieldtypes[name].ctype except KeyError: - raise AttributeError(name) + return _CData.__setattr__(self, name, value) if ensure_objects(value) is not None: key = keepalive_key(getattr(self.__class__, name).num) store_reference(self, key, value._objects) Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_structures.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_structures.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_structures.py Wed Feb 11 00:30:39 2009 @@ -384,6 +384,13 @@ assert p.name == "John Doe" assert p.age == 25 + def test_setattr(self): + class X(Structure): + _fields_ = [("a", c_int)] + + x = X() + x.other = 42 + assert x.other == 42 class TestPointerMember(BaseCTypesTestChecker): From fijal at codespeak.net Wed Feb 11 12:33:02 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 12:33:02 +0100 (CET) Subject: [pypy-svn] r61713 - pypy/branch/pyjitpl5 Message-ID: <20090211113302.34C4B169ECB@codespeak.net> Author: fijal Date: Wed Feb 11 12:33:01 2009 New Revision: 61713 Added: pypy/branch/pyjitpl5/ - copied from r61712, pypy/trunk/ Log: (arigo, fijal) Create a new branch for importing pyjitpl5 into trunk (and pieces from pypy-oo-jit) From fijal at codespeak.net Wed Feb 11 12:39:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 12:39:08 +0100 (CET) Subject: [pypy-svn] r61714 - in pypy/branch/pyjitpl5/pypy/jit: . metainterp tl Message-ID: <20090211113908.BDF81169E79@codespeak.net> Author: fijal Date: Wed Feb 11 12:39:07 2009 New Revision: 61714 Added: pypy/branch/pyjitpl5/pypy/jit/ pypy/branch/pyjitpl5/pypy/jit/__init__.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/metainterp/ - copied from r61713, user/cfbolz/jitpl/branch/pyjitpl5/ pypy/branch/pyjitpl5/pypy/jit/metainterp/__init__.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/tl/ - copied from r61713, pypy/branch/oo-jit/pypy/jit/tl/ Removed: pypy/branch/pyjitpl5/pypy/jit/metainterp/bak-fixclass.py pypy/branch/pyjitpl5/pypy/jit/metainterp/bak-optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/bak-specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/bak-vbool.py pypy/branch/pyjitpl5/pypy/jit/metainterp/bak-vinst.py pypy/branch/pyjitpl5/pypy/jit/metainterp/bak-virtualizable.py pypy/branch/pyjitpl5/pypy/jit/metainterp/bak-vlist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/bak-warmspot.py Log: (arigo, fijal) Import stuff from various places, completely broken Added: pypy/branch/pyjitpl5/pypy/jit/__init__.py ============================================================================== Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/__init__.py ============================================================================== From fijal at codespeak.net Wed Feb 11 12:48:51 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 12:48:51 +0100 (CET) Subject: [pypy-svn] r61715 - in pypy/branch/pyjitpl5/pypy/jit: backend backend/llgraph backend/x86 metainterp metainterp/codegen386 metainterp/llgraph metainterp/test Message-ID: <20090211114851.7D910169EDB@codespeak.net> Author: fijal Date: Wed Feb 11 12:48:49 2009 New Revision: 61715 Added: pypy/branch/pyjitpl5/pypy/jit/backend/ pypy/branch/pyjitpl5/pypy/jit/backend/__init__.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/ - copied from r61714, pypy/branch/pyjitpl5/pypy/jit/metainterp/llgraph/ pypy/branch/pyjitpl5/pypy/jit/backend/x86/ - copied from r61714, pypy/branch/pyjitpl5/pypy/jit/metainterp/codegen386/ Removed: pypy/branch/pyjitpl5/pypy/jit/metainterp/codegen386/ pypy/branch/pyjitpl5/pypy/jit/metainterp/conftest.py pypy/branch/pyjitpl5/pypy/jit/metainterp/llgraph/ Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/ (props changed) pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: (arigo, fijal) Next round, fix a bit of imports and shuffle stuff around Added: pypy/branch/pyjitpl5/pypy/jit/backend/__init__.py ============================================================================== Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Wed Feb 11 12:48:49 2009 @@ -6,15 +6,16 @@ from pypy.objspace.flow.model import Variable, Constant from pypy.annotation import model as annmodel -from history import ConstInt, ConstPtr, ConstAddr, BoxInt, BoxPtr +from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr, + BoxInt, BoxPtr) from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr from pypy.rpython.ootypesystem import ootype from pypy.rpython.module.support import LLSupport, OOSupport from pypy.rpython.llinterp import LLInterpreter, LLFrame, LLException from pypy.rpython.extregistry import ExtRegistryEntry -import heaptracker -from llgraph import symbolic +from pypy.jit.metainterp import heaptracker +from pypy.jit.backend.llgraph import symbolic import py from pypy.tool.ansi_print import ansi_log Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Wed Feb 11 12:48:49 2009 @@ -3,8 +3,8 @@ """ from pypy.rpython.lltypesystem import lltype, llmemory -import history -from llgraph import llimpl, symbolic +from pypy.jit.metainterp import history +from pypy.jit.backend.llgraph import llimpl, symbolic class MiniStats: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Wed Feb 11 12:48:49 2009 @@ -6,12 +6,12 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.debug import debug_print -import history, support -from history import Const, ConstInt, ConstPtr, Box, BoxInt, BoxPtr, GuardOp -from compile import compile_new_loop, compile_new_bridge -from heaptracker import get_vtable_for_gcstruct -import codewriter, optimize -from llgraph import runner +from pypy.jit.metainterp import history, support +from pypy.jit.metainterp.history import (Const, ConstInt, ConstPtr, Box, + BoxInt, BoxPtr, GuardOp) +from pypy.jit.metainterp.compile import compile_new_loop, compile_new_bridge +from pypy.jit.metainterp.heaptracker import get_vtable_for_gcstruct +from pypy.jit.metainterp import codewriter, optimize # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Wed Feb 11 12:48:49 2009 @@ -1,13 +1,9 @@ import py from pypy.rlib.jit import JitDriver, hint -from warmspot import ll_meta_interp, get_stats -import history -from pyjitpl import OOMetaInterp -import pyjitpl -from llgraph import runner -import codewriter -import support -from policy import JitPolicy, StopAtXPolicy +from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats +from pypy.jit.backend.llgraph import runner +from pypy.jit.metainterp import support, codewriter, pyjitpl, history +from pypy.jit.metainterp.policy import JitPolicy, StopAtXPolicy def get_metainterp(func, values, CPUClass, type_system, policy): from pypy.annotation.policy import AnnotatorPolicy @@ -20,7 +16,7 @@ stats = history.Stats() cpu = CPUClass(rtyper, stats, False) graph = rtyper.annotator.translator.graphs[0] - return OOMetaInterp(graph, cpu, stats, False), rtyper + return pyjitpl.OOMetaInterp(graph, cpu, stats, False), rtyper class JitMixin: basic = True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Wed Feb 11 12:48:49 2009 @@ -10,10 +10,10 @@ from pypy.rlib.jit import PARAMETERS from pypy.rlib.rarithmetic import r_uint -import support, history, pyjitpl -from pyjitpl import OOMetaInterp -from llgraph import runner -from policy import JitPolicy +from pypy.jit.metainterp import support, history, pyjitpl +from pypy.jit.metainterp.pyjitpl import OOMetaInterp +from pypy.jit.backend.llgraph import runner +from pypy.jit.metainterp.policy import JitPolicy # ____________________________________________________________ # Bootstrapping From fijal at codespeak.net Wed Feb 11 12:49:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 12:49:27 +0100 (CET) Subject: [pypy-svn] r61716 - in pypy/branch/pyjitpl5/pypy/jit: . backend backend/llgraph backend/x86/test metainterp metainterp/test Message-ID: <20090211114927.4FABA169EDA@codespeak.net> Author: fijal Date: Wed Feb 11 12:49:26 2009 New Revision: 61716 Modified: pypy/branch/pyjitpl5/pypy/jit/ (props changed) pypy/branch/pyjitpl5/pypy/jit/backend/ (props changed) pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (props changed) pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py (props changed) pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (props changed) pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (props changed) Log: fixeol From arigo at codespeak.net Wed Feb 11 12:51:02 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 12:51:02 +0100 (CET) Subject: [pypy-svn] r61717 - pypy/branch/pyjitpl5/pypy Message-ID: <20090211115102.E1C6B169ECD@codespeak.net> Author: arigo Date: Wed Feb 11 12:51:02 2009 New Revision: 61717 Modified: pypy/branch/pyjitpl5/pypy/conftest.py Log: Shut the DeprecationWarning when running py.test. Modified: pypy/branch/pyjitpl5/pypy/conftest.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/conftest.py (original) +++ pypy/branch/pyjitpl5/pypy/conftest.py Wed Feb 11 12:51:02 2009 @@ -516,3 +516,8 @@ # disable recursion in symlinked subdirectories return (py.test.collect.Directory.recfilter(self, path) and path.check(link=0)) + + +import warnings +warnings.filterwarnings('ignore', category=DeprecationWarning, + module='.*ansi_print') From fijal at codespeak.net Wed Feb 11 12:53:26 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 12:53:26 +0100 (CET) Subject: [pypy-svn] r61718 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090211115326.435BE169ECD@codespeak.net> Author: fijal Date: Wed Feb 11 12:53:25 2009 New Revision: 61718 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/rpyjitpl.py Log: fix imports Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Wed Feb 11 12:53:25 2009 @@ -4,8 +4,8 @@ from pypy.objspace.flow.model import Variable, Constant, Link, c_last_exception from pypy.rlib import objectmodel from pypy.rlib.objectmodel import we_are_translated -from history import Const, getkind, getkind_num -import heaptracker, support, history, optimize +from pypy.jit.metainterp.history import Const, getkind, getkind_num +from pypy.jit.metainterp import heaptracker, support, history, optimize import py from pypy.tool.ansi_print import ansi_log Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Wed Feb 11 12:53:25 2009 @@ -4,8 +4,8 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.conftest import option -from history import Graph, Jump, log, Box -import optimize +from pypy.jit.metainterp.history import Graph, Jump, log, Box +from pypy.jit.metainterp import optimize def compile_new_loop(metainterp, old_loops, endliveboxes): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py Wed Feb 11 12:53:25 2009 @@ -1,4 +1,4 @@ -import codewriter +from pypy.jit.metainterp import codewriter class SourceIterator: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Wed Feb 11 12:53:25 2009 @@ -1,7 +1,7 @@ from pypy.translator.tool.graphpage import GraphPage from pypy.translator.tool.make_dot import DotGen -from history import Box +from pypy.jit.metainterp.history import Box class ResOpGraphPage(GraphPage): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Wed Feb 11 12:53:25 2009 @@ -356,7 +356,7 @@ def show(self, in_stats=None, errmsg=None, highlightops={}): if in_stats is None: - from graphpage import ResOpGraphPage + from pypy.jit.metainterp.graphpage import ResOpGraphPage ResOpGraphPage([self], errmsg, highlightops).display() else: h = dict.fromkeys(self.operations) @@ -507,7 +507,7 @@ self.view() def view(self, errmsg=None, extragraphs=[], highlightops={}): - from graphpage import ResOpGraphPage + from pypy.jit.metainterp.graphpage import ResOpGraphPage graphs = self.get_all_graphs() for graph in extragraphs: if graph in graphs: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Wed Feb 11 12:53:25 2009 @@ -1,7 +1,6 @@ -from history import Box, Const, ConstInt -from history import MergePoint, ResOperation, Jump -from heaptracker import always_pure_operations - +from pypy.jit.metainterp.history import (Box, Const, ConstInt, + MergePoint, ResOperation, Jump) +from pypy.jit.metainterp.heaptracker import always_pure_operations class CancelInefficientLoop(Exception): pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/rpyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/rpyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/rpyjitpl.py Wed Feb 11 12:53:25 2009 @@ -4,10 +4,10 @@ from pypy.rpython import annlowlevel from pypy.annotation import model as annmodel -from pyjitpl import build_meta_interp, generate_bootstrapping_code, MIFrame -from pyjitpl import debug_checks -from history import ResOperation, Const, Box, BoxInt, log -import history, specnode +from pypy.jit.metainterp.pyjitpl import (build_meta_interp, debug_checks, + generate_bootstrapping_code, MIFrame) +from pypy.jit.metainterp.history import ResOperation, Const, Box, BoxInt, log +from pypy.jit.metainterp import history, specnode def rpython_ll_meta_interp(function, args, loops=None, **kwds): From fijal at codespeak.net Wed Feb 11 12:59:47 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 12:59:47 +0100 (CET) Subject: [pypy-svn] r61719 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090211115947.B0348169EDA@codespeak.net> Author: fijal Date: Wed Feb 11 12:59:46 2009 New Revision: 61719 Removed: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vbool.py Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop_spec.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: (arigo, fijal) Fix imports and remove test_vbool Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Wed Feb 11 12:59:46 2009 @@ -1,7 +1,7 @@ import py -from test.test_basic import LLJitMixin, OOJitMixin +from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, hint -from policy import StopAtXPolicy +from pypy.jit.metainterp.policy import StopAtXPolicy class ExceptionTests: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Wed Feb 11 12:59:46 2009 @@ -1,9 +1,9 @@ import py from pypy.rlib.jit import JitDriver -from warmspot import ll_meta_interp, get_stats +from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.rpython.lltypesystem import lltype -from test.test_basic import LLJitMixin -from policy import StopAtXPolicy +from pypy.jit.metainterp.test.test_basic import LLJitMixin +from pypy.jit.metainterp.policy import StopAtXPolicy class TestLoop(LLJitMixin): specialize = False Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop_spec.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop_spec.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop_spec.py Wed Feb 11 12:59:46 2009 @@ -1,5 +1,5 @@ import py -import test_loop +from pypy.jit.metainterp.test import test_loop class TestLoopSpec(test_loop.TestLoop): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Wed Feb 11 12:59:46 2009 @@ -4,13 +4,13 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE -from llgraph import runner -from history import BoxInt, BoxPtr, ConstInt, ConstPtr, ConstAddr -from history import ResOperation, MergePoint, Jump, GuardOp -from optimize import PerfectSpecializer, CancelInefficientLoop -from optimize import VirtualInstanceSpecNode, FixedClassSpecNode -from optimize import rebuild_boxes_from_guard_failure, type_cache -from optimize import AllocationStorage +from pypy.jit.backend.llgraph import runner +from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, + ConstAddr, ResOperation, MergePoint, + Jump, GuardOp) +from pypy.jit.metainterp.optimize import (PerfectSpecializer, + CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, + rebuild_boxes_from_guard_failure, type_cache, AllocationStorage) cpu = runner.CPU(None) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Wed Feb 11 12:59:46 2009 @@ -1,8 +1,8 @@ import py from pypy.rlib.jit import JitDriver -from policy import StopAtXPolicy +from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype -from test.test_basic import LLJitMixin, OOJitMixin +from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin class SendTests: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Wed Feb 11 12:59:46 2009 @@ -1,6 +1,6 @@ import py -from policy import StopAtXPolicy -from test.test_basic import LLJitMixin, OOJitMixin +from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, hint class ListTests: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_support.py Wed Feb 11 12:59:46 2009 @@ -1,7 +1,7 @@ import py from pypy.rpython.lltypesystem import lltype from pypy.objspace.flow.model import Variable, Constant, SpaceOperation -from support import decode_builtin_call +from pypy.jit.metainterp.support import decode_builtin_call def newconst(x): return Constant(x, lltype.typeOf(x)) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Wed Feb 11 12:59:46 2009 @@ -1,7 +1,7 @@ import py from pypy.rlib.jit import JitDriver, hint -from policy import StopAtXPolicy -from test.test_basic import OOJitMixin, LLJitMixin +from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin class ToyLanguageTests: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Feb 11 12:59:46 2009 @@ -1,4 +1,5 @@ import py +py.test.skip("look later") from pypy.rlib.jit import JitDriver, hint from pypy.jit.hintannotator.policy import StopAtXPolicy from pyjitpl import oo_meta_interp, get_stats From fijal at codespeak.net Wed Feb 11 13:05:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 13:05:04 +0100 (CET) Subject: [pypy-svn] r61720 - in pypy/branch/pyjitpl5/pypy/jit: metainterp/test tl Message-ID: <20090211120504.F128A169EE0@codespeak.net> Author: fijal Date: Wed Feb 11 13:05:04 2009 New Revision: 61720 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/tl/tlr.py Log: (arigo, fijal) Simplify tlr by removing hints and make test_tl pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Wed Feb 11 13:05:04 2009 @@ -34,12 +34,12 @@ assert res == 120 def test_tlr(self): - from pypy.jit.tl.tlr import hp_interpret, SQUARE + from pypy.jit.tl.tlr import interpret, SQUARE codes = ["", SQUARE] def main(n, a): - code = hint(codes, deepfreeze=True)[n] - return hp_interpret(code, a) + code = codes[n] + return interpret(code, a) res = self.meta_interp(main, [1, 10]) assert res == 100 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tlr.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tlr.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tlr.py Wed Feb 11 13:05:04 2009 @@ -1,5 +1,5 @@ import autopath -from pypy.rlib.jit import hint, JitDriver +from pypy.rlib.jit import JitDriver MOV_A_R = 1 @@ -11,72 +11,18 @@ ALLOCATE = 7 NEG_A = 8 - -def interpret(bytecode, a): - """Another Toy Language interpreter, this one register-based.""" - regs = [] - pc = 0 - while True: - hint(None, global_merge_point=True) - opcode = hint(ord(bytecode[pc]), concrete=True) - pc += 1 - if opcode == MOV_A_R: - n = ord(bytecode[pc]) - pc += 1 - regs[n] = a - elif opcode == MOV_R_A: - n = ord(bytecode[pc]) - pc += 1 - a = regs[n] - elif opcode == JUMP_IF_A: - target = ord(bytecode[pc]) - pc += 1 - if a: - pc = target - elif opcode == SET_A: - a = ord(bytecode[pc]) - pc += 1 - elif opcode == ADD_R_TO_A: - n = ord(bytecode[pc]) - pc += 1 - a += regs[n] - elif opcode == RETURN_A: - return a - elif opcode == ALLOCATE: - n = ord(bytecode[pc]) - pc += 1 - regs = [0] * n - elif opcode == NEG_A: - a = -a - - class TLRJitDriver(JitDriver): greens = ['bytecode', 'pc'] reds = ['a', 'regs'] - def compute_invariants(self, reds, bytecode, pc): - return len(reds.regs) - - def on_enter_jit(self, invariant, reds, bytecode, pc): - # make a copy of the 'regs' list to make it a VirtualList for the JIT - length = invariant - newregs = [0] * length - i = 0 - while i < length: - i = hint(i, concrete=True) - newregs[i] = reds.regs[i] - i += 1 - reds.regs = newregs - tlrjitdriver = TLRJitDriver() -def hp_interpret(bytecode, a): - """A copy of interpret() with the hints required by the hotpath policy.""" +def interpret(bytecode, a): regs = [] pc = 0 while True: tlrjitdriver.jit_merge_point(bytecode=bytecode, pc=pc, a=a, regs=regs) - opcode = hint(ord(bytecode[pc]), concrete=True) + opcode = ord(bytecode[pc]) pc += 1 if opcode == MOV_A_R: n = ord(bytecode[pc]) From arigo at codespeak.net Wed Feb 11 14:05:23 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 14:05:23 +0100 (CET) Subject: [pypy-svn] r61724 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090211130523.AA161169E82@codespeak.net> Author: arigo Date: Wed Feb 11 14:05:22 2009 New Revision: 61724 Removed: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/bak-test_optimize.py Log: Killl another bak-*.py. From antocuni at codespeak.net Wed Feb 11 14:15:55 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 11 Feb 2009 14:15:55 +0100 (CET) Subject: [pypy-svn] r61725 - in pypy/branch/oo-jit/pypy/jit/codegen/cli: . test Message-ID: <20090211131555.B1DF2169EE7@codespeak.net> Author: antocuni Date: Wed Feb 11 14:15:55 2009 New Revision: 61725 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Log: (in-progress) a bit of refactoring, the goal is to support more raising ops Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Wed Feb 11 14:15:55 2009 @@ -340,10 +340,12 @@ def emit(self): self.meth.il.EmitWriteLine(self.message) -class IntAddOvf(BinaryOp): +class CatchAndRaiseMixin(object): - def getOpCode(self): - return OpCodes.Add_Ovf + _mixin_ = True + + def getExceptionType(self): + raise NotImplementedError def emit(self): il = self.meth.il @@ -352,13 +354,28 @@ il.Emit(self.getOpCode()) self.storeResult() il.Emit(OpCodes.Leave, lbl) - - il.BeginCatchBlock(typeof(System.OverflowException)) + il.BeginCatchBlock(self.getExceptionType()) il.Emit(OpCodes.Ldc_I4, 1) self.storeExcFlag() il.EndExceptionBlock() +class RaisingBinaryOp(CatchAndRaiseMixin, BinaryOp): + pass + +class RaisingUnaryOp(CatchAndRaiseMixin, UnaryOp): + pass + + +class IntAddOvf(RaisingBinaryOp): + + def getOpCode(self): + return OpCodes.Add_Ovf + + def getExceptionType(self): + return typeof(System.OverflowException) + + def opcode2attrname(opcode): if opcode == 'ldc.r8 0': return 'Ldc_R8, 0' # XXX this is a hack @@ -387,33 +404,68 @@ def fillops(ops, baseclass): out = {} for opname, value in ops.iteritems(): - if isinstance(value, str): - attrname = opcode2attrname(value) - source = py.code.Source(""" - class %(opname)s (%(baseclass)s): - def getOpCode(self): - return OpCodes.%(attrname)s - """ % locals()) - code = source.compile() - exec code in globals(), out - elif value is cli_opcodes.DoNothing: - # create a new subclass of SameAs; we can't use SameAs directly - # because its restype could be patched later - out[opname] = type(opname, (SameAs,), {}) - else: - renderCustomOp(opname, baseclass, value, out) - - # fix the restype for comparison ops and casts - if is_comparison(opname): - out[opname].restype = restype_bool - elif opname != 'cast_primitive' and opname.startswith('cast_'): - _, _, _, to = opname.split('_') - funcname = 'restype_%s' % to - out[opname].restype = globals()[funcname] + renderOp(baseclass, opname, value, out) return out -def renderCustomOp(opname, baseclass, steps, out): +def renderOp(baseclass, opname, value, out, optional_lines=''): + if isinstance(value, str): + renderSimpleOp(baseclass, opname, value, out, optional_lines) + elif value is cli_opcodes.DoNothing: + # create a new subclass of SameAs; we can't use SameAs directly + # because its restype could be patched later + out[opname] = type(opname, (SameAs,), {}) + else: + assert isinstance(value, list) + steps = value + if len(steps) == 1 and isinstance(steps[0], cli_opcodes.MapException): + #renderRaisingOp(baseclass, opname, steps[0], out) + return # XXX + renderCustomOp(baseclass, opname, value, out) + + # fix the restype for comparison ops and casts + if is_comparison(opname): + out[opname].restype = restype_bool + elif opname != 'cast_primitive' and opname.startswith('cast_'): + _, _, _, to = opname.split('_') + funcname = 'restype_%s' % to + out[opname].restype = globals()[funcname] + +def renderSimpleOp(baseclass, opname, value, out, optional_lines=''): + attrname = opcode2attrname(value) + source = py.code.Source(""" + class %(opname)s (%(baseclass)s): + def getOpCode(self): + return OpCodes.%(attrname)s + +%(optional_lines)s + """ % locals()) + code = source.compile() + exec code in globals(), out + +## def get_exctype(exctype_str): +## if exctype_str == '[mscorlib]System.OverflowException': +## return typeof(System.OverflowException) +## elif exctype_str == '[mscorlib]System.DivideByZeroException': +## return typeof(System.DivideByZeroException) +## else: +## assert False, 'Unknown exception type' + +## def renderRaisingOp(baseclass, opname, value, out): +## mapping = value.mapping +## assert len(mapping) == 1, 'Catching more than one exception is not supported' +## exctype = mapping[0][0] +## assert exctype.startswith('[mscorlib]') +## exctype = exctype[len('[mscorlib]'):] +## source = """ +## def getExceptionType(self): +## return typeof(%(exctype)s) +## """ % locals() +## baseclass = 'Raising' + baseclass +## renderOp(baseclass, opname, value.instr, out, source) + + +def renderCustomOp(baseclass, opname, steps, out): assert steps body = [] for step in steps: Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Wed Feb 11 14:15:55 2009 @@ -66,6 +66,9 @@ def test_from_random_5_direct(self): py.test.skip('mono crash') + def test_longwinded_and_direct(self): + py.test.skip('mono 2.2 crashes') + def test_ovfcheck1_direct(self): py.test.skip('fixme') From fijal at codespeak.net Wed Feb 11 14:17:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 14:17:19 +0100 (CET) Subject: [pypy-svn] r61726 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090211131719.C5D71168450@codespeak.net> Author: fijal Date: Wed Feb 11 14:17:18 2009 New Revision: 61726 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py Log: (arigo, fijal) Implement switches and fix imports, so more tests pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Wed Feb 11 14:17:18 2009 @@ -248,7 +248,23 @@ self.emit(*falserenaming) self.make_bytecode_block(linkfalse.target) else: - xxx + self.minimize_variables() + switches = [link for link in block.exits + if link.exitcase != 'default'] + renamings = [self.insert_renaming(link.args) + for link in switches] + self.emit("switch", + self.var_position(block.exitswitch)) + self.emit_list([link.llexitcase for link in switches]) + self.emit_list([tlabel(link) for link in switches]) + if block.exits[-1].exitcase == 'default': + link = block.exits[-1] + self.emit(*self.insert_renaming(link.args)) + self.make_bytecode_block(link.target) + for renaming, link in zip(renamings, switches): + self.emit(label(link)) + self.emit(*renaming) + self.make_bytecode_block(link.target) def serialize_setup_exception_block(self, exception_exits): self.minimize_variables() @@ -647,8 +663,11 @@ self.assembler.extend(stuff) def emit_varargs(self, varargs): - self.emit(len(varargs)) - self.emit(*map(self.var_position, varargs)) + self.emit_list(map(self.var_position, varargs)) + + def emit_list(self, l): + self.emit(len(l)) + self.emit(*l) # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Wed Feb 11 14:17:18 2009 @@ -52,7 +52,7 @@ args += (self.load_3byte(), ) elif argspec == "jumptargets": num = self.load_int() - args += ([self.load_4byte() for i in range(num)], ) + args += ([self.load_3byte() for i in range(num)], ) elif argspec == "bool": args += (self.load_bool(), ) elif argspec == "2byte": @@ -269,6 +269,17 @@ self.generate_guard(targetpc, opname, box, ignore_box=switchcase) self.pc = currentpc + @arguments("orgpc", "box", "intargs", "jumptargets") + def opimpl_switch(self, pc, valuebox, intargs, jumptargets): + box = self.implement_guard_value(pc, valuebox) + switchcase = box.getint() + # XXX implement dictionary for speedups at some point + for i in range(len(intargs)): + value = intargs[i] + if switchcase == value: + self.pc = jumptargets[i] + break + @arguments("int") def opimpl_new(self, size): self.execute('new', [ConstInt(size)], 'ptr') @@ -433,12 +444,7 @@ @arguments("orgpc", "box", returns="box") def opimpl_guard_value(self, pc, box): - if isinstance(box, Box): - promoted_box = box.constbox() - self.generate_guard(pc, 'guard_value', box, [promoted_box]) - return promoted_box - else: - return box # no promotion needed, already a Const + return self.implement_guard_value(pc, box) @arguments("orgpc", "box", returns="box") def opimpl_guard_class(self, pc, box): @@ -582,6 +588,14 @@ guard_op.key = self.metainterp.record_state() self.pc = saved_pc + def implement_guard_value(self, pc, box): + if isinstance(box, Box): + promoted_box = box.constbox() + self.generate_guard(pc, 'guard_value', box, [promoted_box]) + return promoted_box + else: + return box # no promotion needed, already a Const + def follow_jump(self): self.pc -= 3 self.pc = self.load_3byte() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Wed Feb 11 14:17:18 2009 @@ -74,7 +74,7 @@ codes = ["", code] def main(n): - code = hint(codes, deepfreeze=True)[n] + code = codes[n] return interp(code) res = self.meta_interp(main, [1]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Wed Feb 11 14:17:18 2009 @@ -1,4 +1,5 @@ import py +py.test.skip("XXX") from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR from pypy.rpython.lltypesystem import lltype, lloperation from pypy.rpython.annlowlevel import llhelper Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Wed Feb 11 14:17:18 2009 @@ -1,4 +1,5 @@ import py +py.test.skip("XXX") from pypy.rlib.jit import JitDriver, hint from pypy.jit.hintannotator.policy import StopAtXPolicy from pyjitpl import get_stats Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py Wed Feb 11 14:17:18 2009 @@ -1,4 +1,4 @@ -from warmspot import ll_meta_interp +from pypy.jit.metainterp.warmspot import ll_meta_interp from pypy.rlib.jit import hint, JitDriver class Exit(Exception): From afa at codespeak.net Wed Feb 11 14:23:19 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Feb 2009 14:23:19 +0100 (CET) Subject: [pypy-svn] r61727 - pypy/trunk/pypy/module/_rawffi/test Message-ID: <20090211132319.6E603169ECC@codespeak.net> Author: afa Date: Wed Feb 11 14:23:19 2009 New Revision: 61727 Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Log: Avoid "import plaform" at applevel: this module has too many dependencies and is very slow. Compute the result (isx86_64) before and make it an applevel constant. Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Wed Feb 11 14:23:19 2009 @@ -172,6 +172,8 @@ cls.w_libm_name = space.wrap('libm.so') if sys.platform == "darwin": cls.w_libm_name = space.wrap('libm.dylib') + import platform + cls.w_isx86_64 = space.wrap(platform.machine() == 'x86_64') cls.w_sizes_and_alignments = space.wrap(dict( [(k, (v.c_size, v.c_alignment)) for k,v in TYPEMAP.iteritems()])) @@ -735,12 +737,13 @@ raises(_rawffi.SegfaultException, a.__setitem__, 3, 3) def test_struct_byvalue(self): - import _rawffi, platform - if platform.machine() == 'x86_64': + import _rawffi + if self.isx86_64: skip("Segfaults on x86_64 because small structures " "may be passed in registers and " "c_elements must not be null") + import _rawffi X_Y = _rawffi.Structure([('x', 'l'), ('y', 'l')]) x_y = X_Y() lib = _rawffi.CDLL(self.lib_name) @@ -752,12 +755,12 @@ x_y.free() def test_ret_struct(self): - import _rawffi, platform - if platform.machine() == 'x86_64': + if self.isx86_64: skip("Segfaults on x86_64 because small structures " "may be passed in registers and " "c_elements must not be null") + import _rawffi S2H = _rawffi.Structure([('x', 'h'), ('y', 'h')]) s2h = S2H() lib = _rawffi.CDLL(self.lib_name) From fijal at codespeak.net Wed Feb 11 14:27:54 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 14:27:54 +0100 (CET) Subject: [pypy-svn] r61728 - in pypy/branch/pyjitpl5/pypy/jit: metainterp/test tl Message-ID: <20090211132754.08A14169ECC@codespeak.net> Author: fijal Date: Wed Feb 11 14:27:51 2009 New Revision: 61728 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_slist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_virtualizable.py pypy/branch/pyjitpl5/pypy/jit/tl/tl.py pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py Log: (arigo, fijal) * adapt tl and tlc for a new jit * pass or skip most of tests Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Wed Feb 11 14:27:51 2009 @@ -4,7 +4,7 @@ from pypy.jit.tl import tlc -from test.test_basic import OOJitMixin, LLJitMixin +from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin class TLCTests: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py Wed Feb 11 14:27:51 2009 @@ -1,4 +1,5 @@ import py +py.test.skip("XXX") from pyjitpl import ll_meta_interp, get_stats from rpyjitpl import rpython_ll_meta_interp from test import test_basic Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_send.py Wed Feb 11 14:27:51 2009 @@ -1,6 +1,6 @@ import py -from test import test_send -from test.test_zrpy_basic import LLInterpJitMixin +from pypy.jit.metainterp.test import test_send +from pypy.jit.metainterp.test.test_zrpy_basic import LLInterpJitMixin class TestLLSend(test_send.SendTests, LLInterpJitMixin): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_slist.py Wed Feb 11 14:27:51 2009 @@ -1,6 +1,6 @@ import py -from test import test_slist -from test.test_zrpy_basic import LLInterpJitMixin +from pypy.jit.metainterp.test import test_slist +from pypy.jit.metainterp.test.test_zrpy_basic import LLInterpJitMixin class TestLLList(test_slist.ListTests, LLInterpJitMixin): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_virtualizable.py Wed Feb 11 14:27:51 2009 @@ -1,6 +1,6 @@ import py -from test import test_virtualizable -from test.test_zrpy_basic import LLInterpJitMixin +from pypy.jit.metainterp.test import test_virtualizable +from pypy.jit.metainterp.test.test_zrpy_basic import LLInterpJitMixin class TestLLImplicitVirtualizable(LLInterpJitMixin, Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Wed Feb 11 14:27:51 2009 @@ -2,7 +2,7 @@ import py from pypy.jit.tl.tlopcode import * -from pypy.rlib.jit import hint +from pypy.rlib.jit import JitDriver def char2int(c): t = ord(c) @@ -11,6 +11,8 @@ return t def make_interp(supports_call): + myjitdriver = JitDriver(greens = ['pc', 'code', 'code_len'], + reds = ['stack', 'inputarg']) def interp(code='', pc=0, inputarg=0): if not isinstance(code,str): raise TypeError("code '%s' should be a string" % str(code)) @@ -19,8 +21,9 @@ stack = [] while pc < code_len: + myjitdriver.jit_merge_point(pc=pc, code=code, code_len=code_len, + stack=stack, inputarg=inputarg) opcode = ord(code[pc]) - opcode = hint(opcode, concrete=True) pc += 1 if opcode == NOP: @@ -103,13 +106,20 @@ elif opcode == BR_COND: if stack.pop(): - pc += char2int(code[pc]) - pc += 1 + pc += char2int(code[pc]) + 1 + myjitdriver.can_enter_jit(pc=pc, code=code, + code_len=code_len, + stack=stack, inputarg=inputarg) + else: + pc += 1 elif opcode == BR_COND_STK: offset = stack.pop() if stack.pop(): - pc += hint(offset, forget=True) + pc += offset + myjitdriver.can_enter_jit(pc=pc, code=code, + code_len=code_len, + stack=stack, inputarg=inputarg) elif supports_call and opcode == CALL: offset = char2int(code[pc]) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py Wed Feb 11 14:27:51 2009 @@ -5,7 +5,7 @@ from pypy.rlib.objectmodel import specialize, we_are_translated from pypy.jit.tl.tlopcode import * from pypy.jit.tl import tlopcode -from pypy.rlib.jit import hint +from pypy.rlib.jit import JitDriver class Obj(object): @@ -95,13 +95,10 @@ def __init__(self, cls): self.cls = cls - frozenclass = hint(cls, deepfreeze=True) - self.values = [nil] * len(frozenclass.attributes) + self.values = [nil] * len(cls.attributes) def getclass(self): - # promote and deepfreeze the class - cls = hint(self.cls, promote=True) - return hint(cls, deepfreeze=True) + return self.cls def to_string(self): return '' @@ -241,18 +238,8 @@ return len(self.pc_stack) == 0 def make_interp(supports_call, jitted=True): - if jitted: - from pypy.rlib.jit import hint - else: - @specialize.argtype(0) - def hint(x, global_merge_point=False, - promote_class=False, - promote=False, - deepfreeze=False, - forget=False, - concrete=False): - return x - + myjitdriver = JitDriver(greens = ['code', 'pc'], + reds = ['pool', 'args', 'stack', 'framestack']) def interp(code='', pc=0, inputarg=0, pool=None): if not isinstance(code,str): raise TypeError("code '%s' should be a string" % str(code)) @@ -262,16 +249,14 @@ args = [IntObj(inputarg)] return interp_eval(code, pc, args, pool).int_o() - def interp_eval(code, pc, args, pool2): - code_len = len(code) - pool = hint(hint(pool2, concrete=True), deepfreeze=True) + def interp_eval(code, pc, args, pool): stack = [] framestack = FrameStack() - while pc < code_len: - hint(None, global_merge_point=True) + while pc < len(code): + myjitdriver.jit_merge_point(code=code, pc=pc, pool=pool, args=args, + stack=stack, framestack=framestack) opcode = ord(code[pc]) - opcode = hint(opcode, concrete=True) pc += 1 if opcode == NOP: @@ -327,79 +312,78 @@ elif opcode == ADD: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(b.add(a)) elif opcode == SUB: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(b.sub(a)) elif opcode == MUL: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(b.mul(a)) elif opcode == DIV: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(b.div(a)) elif opcode == EQ: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(IntObj(b.eq(a))) elif opcode == NE: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(IntObj(not b.eq(a))) elif opcode == LT: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(IntObj(b.lt(a))) elif opcode == LE: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(IntObj(not a.lt(b))) elif opcode == GT: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(IntObj(a.lt(b))) elif opcode == GE: a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) stack.append(IntObj(not b.lt(a))) elif opcode == BR: + old_pc = pc pc += char2int(code[pc]) pc += 1 + if old_pc > pc: + myjitdriver.can_enter_jit(code=code, pc=pc, pool=pool, + args=args, + stack=stack, + framestack=framestack) elif opcode == BR_COND: cond = stack.pop() - hint(cond, promote_class=True) if cond.t(): - pc += char2int(code[pc]) - pc += 1 - + old_pc = pc + pc += char2int(code[pc]) + 1 + if old_pc > pc: + myjitdriver.can_enter_jit(code=code, pc=pc, pool=pool, + args=args, + stack=stack, + framestack=framestack) + else: + pc += 1 + elif opcode == BR_COND_STK: offset = stack.pop().int_o() if stack.pop().t(): - pc += hint(offset, forget=True) + old_pc = pc + pc += offset + if old_pc > pc: + myjitdriver.can_enter_jit(code=code, pc=pc, pool=pool, + args=args, + stack=stack, + framestack=framestack) + elif supports_call and opcode == CALL: offset = char2int(code[pc]) @@ -416,8 +400,7 @@ res = stack.pop() else: res = None - pc2, args, stack = framestack.pop() - pc = hint(pc2, promote=True) + pc, args, stack = framestack.pop() if res: stack.append(res) @@ -441,7 +424,6 @@ pc += 1 name = pool.strings[idx] a = stack.pop() - hint(a, promote_class=True) stack.append(a.getattr(name)) elif opcode == SETATTR: @@ -449,8 +431,6 @@ pc += 1 name = pool.strings[idx] a, b = stack.pop(), stack.pop() - hint(a, promote_class=True) - hint(b, promote_class=True) b.setattr(name, a) elif supports_call and opcode == SEND: @@ -464,10 +444,8 @@ while num_args > 0: num_args -= 1 meth_args[num_args] = stack.pop() - hint(num_args, concrete=True) a = meth_args[0] - hint(a, promote_class=True) - meth_pc = hint(a.send(name), promote=True) + meth_pc = a.send(name) framestack.push(pc, args, stack) pc = meth_pc args = meth_args @@ -476,14 +454,12 @@ elif opcode == PRINT: if not we_are_translated(): a = stack.pop() - hint(a, promote_class=True) print a.to_string() elif opcode == DUMP: if not we_are_translated(): parts = [] for obj in stack: - hint(obj, promote_class=True) parts.append(obj.to_string()) print '[%s]' % ', '.join(parts) From afa at codespeak.net Wed Feb 11 14:42:56 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Feb 2009 14:42:56 +0100 (CET) Subject: [pypy-svn] r61729 - pypy/trunk/pypy/lib/_ctypes Message-ID: <20090211134256.EB1E6169E77@codespeak.net> Author: afa Date: Wed Feb 11 14:42:54 2009 New Revision: 61729 Modified: pypy/trunk/pypy/lib/_ctypes/function.py Log: Run the loop up to 128 = 32*4. Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Wed Feb 11 14:42:54 2009 @@ -159,7 +159,7 @@ # For stdcall, try mangled names: # funcname -> _funcname@ # where n is 0, 4, 8, 12, ..., 128 - for i in range(32): + for i in range(33): mangled_name = "_%s@%d" % (self.name, i*4) try: return cdll.ptr(mangled_name, argshapes, resshape, From arigo at codespeak.net Wed Feb 11 14:44:34 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 14:44:34 +0100 (CET) Subject: [pypy-svn] r61730 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090211134434.2D4F4169EC6@codespeak.net> Author: arigo Date: Wed Feb 11 14:44:33 2009 New Revision: 61730 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py Log: (fijal, arigo) Port from the oo-jit branch. Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py Wed Feb 11 14:44:33 2009 @@ -1,11 +1,11 @@ from pypy.rpython.lltypesystem.lltype import GcArray, Array, Char, malloc -from pypy.rpython.annlowlevel import llstr from pypy.rlib.rarithmetic import r_uint, formatd CHAR_ARRAY = GcArray(Char) def ll_int_str(repr, i): return ll_int2dec(i) +ll_int_str._pure_function_ = True def ll_int2dec(i): from pypy.rpython.lltypesystem.rstr import mallocstr @@ -37,6 +37,7 @@ result.chars[j] = temp[len-j-1] j += 1 return result +ll_int2dec._pure_function_ = True hex_chars = malloc(Array(Char), 16, immortal=True) @@ -78,6 +79,7 @@ result.chars[j] = temp[len-j-1] j += 1 return result +ll_int2hex._pure_function_ = True def ll_int2oct(i, addPrefix): from pypy.rpython.lltypesystem.rstr import mallocstr @@ -114,7 +116,8 @@ result.chars[j] = temp[len-j-1] j += 1 return result +ll_int2oct._pure_function_ = True def ll_float_str(repr, f): - return llstr(formatd("%f", f)) - + return formatd("%f", f) +ll_float_str._pure_function_ = True From arigo at codespeak.net Wed Feb 11 14:45:06 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 14:45:06 +0100 (CET) Subject: [pypy-svn] r61731 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090211134506.62EA4169ECC@codespeak.net> Author: arigo Date: Wed Feb 11 14:45:05 2009 New Revision: 61731 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: (fijal, arigo) Use the '_pure_function_' hint again. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py Wed Feb 11 14:45:05 2009 @@ -2,7 +2,11 @@ class JitPolicy: def graphs_from(self, op): if op.opname == 'direct_call': - return [op.args[0].value._obj.graph] + graph = op.args[0].value._obj.graph + # explicitly pure functions are always opaque + if getattr(getattr(graph, 'func', None), '_pure_function_', False): + return None + return [graph] assert op.opname == 'indirect_call' return op.args[-1].value @@ -24,7 +28,7 @@ def graphs_from(self, op): graphs = JitPolicy.graphs_from(self, op) - if len(graphs) > 1: # XXX a hack + if graphs is None or len(graphs) > 1: # XXX a hack return graphs [graph] = graphs if getattr(graph, 'func', None) in self.funcs: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Wed Feb 11 14:45:05 2009 @@ -45,7 +45,7 @@ assert res == 100 def test_tl_base(self): - from pypy.jit.tl.tl import interp + from pypy.jit.tl.tl import interp_without_call from pypy.jit.tl.tlopcode import compile code = compile(''' @@ -73,11 +73,11 @@ ''') codes = ["", code] - def main(n): + def main(n, inputarg): code = codes[n] - return interp(code) + return interp_without_call(code, inputarg=inputarg) - res = self.meta_interp(main, [1]) + res = self.meta_interp(main, [1, 6]) assert res == 5040 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Wed Feb 11 14:45:05 2009 @@ -96,6 +96,9 @@ graph = copygraph(graph) graph.startblock = support.split_before_jit_merge_point( *find_jit_merge_point([graph])) + for v in graph.getargs(): + assert isinstance(v, Variable) + assert len(dict.fromkeys(graph.getargs())) == len(graph.getargs()) self.translator.graphs.append(graph) self.portal_graph = graph self.jitdriver = block.operations[pos].args[1].value From fijal at codespeak.net Wed Feb 11 15:19:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 15:19:09 +0100 (CET) Subject: [pypy-svn] r61732 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090211141909.BF3AA169E7E@codespeak.net> Author: fijal Date: Wed Feb 11 15:19:08 2009 New Revision: 61732 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Log: (arigo, fijal) Make a next test for automatically promoting vars from whatever they are to greens at merge point Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Wed Feb 11 15:19:08 2009 @@ -506,7 +506,8 @@ assert self.portal, "jit_marker in non-main graph!" if op.args[0].value == 'jit_merge_point': self.emit('jit_merge_point') - self.emit_varargs(op.args[2:]) + assert ([self.var_position(i) for i in op.args[2:]] == + range(0, 2*(len(op.args) - 2), 2)) elif op.args[0].value == 'can_enter_jit': self.emit('can_enter_jit') self.emit_varargs(op.args[2:]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Wed Feb 11 15:19:08 2009 @@ -486,18 +486,21 @@ def opimpl_keepalive(self, box): pass # xxx? - def _check_for_black_hole(self, varargs): + def generate_merge_point(self, pc, varargs): if isinstance(self.metainterp.history, history.BlackHole): - raise self.metainterp.ContinueRunningNormally(varargs) + raise self.metainterp.ContinueRunningNormally(varargs) + num_green_args = self.metainterp.warmrunnerdesc.num_green_args + for i in range(num_green_args): + varargs[i] = self.implement_guard_value(pc, varargs[i]) - @arguments("varargs") - def opimpl_can_enter_jit(self, varargs): - self._check_for_black_hole(varargs) + @arguments("orgpc", "varargs") + def opimpl_can_enter_jit(self, pc, varargs): + self.generate_merge_point(pc, varargs) raise GenerateMergePoint(varargs) - @arguments("varargs") - def opimpl_jit_merge_point(self, varargs): - self._check_for_black_hole(varargs) + @arguments("orgpc") + def opimpl_jit_merge_point(self, pc): + self.generate_merge_point(pc, self.env) @arguments("jumptarget") def opimpl_setup_exception_block(self, exception_target): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Wed Feb 11 15:19:08 2009 @@ -280,3 +280,89 @@ loops = get_stats().loops assert loops[0].operations[0].opname == 'merge_point' assert loops[1].operations[0].opname == 'catch' + + + def test_example(self): + myjitdriver = JitDriver(greens = ['i'], + reds = ['res', 'a']) + CO_INCREASE = 0 + CO_JUMP_BACK_3 = 1 + CO_DECREASE = 2 + + code = [CO_INCREASE, CO_INCREASE, CO_INCREASE, + CO_JUMP_BACK_3, CO_INCREASE, CO_DECREASE] + + def add(res, a): + return res + a + + def sub(res, a): + return res - a + + def main_interpreter_loop(a): + i = 0 + res = 0 + c = len(code) + while i < c: + myjitdriver.jit_merge_point(res=res, i=i, a=a) + elem = code[i] + if elem == CO_INCREASE: + res = add(res, a) + elif elem == CO_DECREASE: + res = sub(res, a) + else: + if res > 100: + pass + else: + i = i - 3 + myjitdriver.can_enter_jit(res=res, i=i, a=a) + continue + i = i + 1 + return res + + res = self.meta_interp(main_interpreter_loop, [1]) + assert res == 102 + self.check_loop_count(1) + self.check_loops({'merge_point' : 1, 'int_add' : 3, 'int_gt' : 1, + 'guard_false' : 1, 'jump' : 1}) + + def test_automatic_promotion(self): + myjitdriver = JitDriver(greens = ['i'], + reds = ['res', 'a']) + CO_INCREASE = 0 + CO_JUMP_BACK_3 = 1 + + code = [CO_INCREASE, CO_INCREASE, CO_INCREASE, + CO_JUMP_BACK_3, CO_INCREASE] + + def add(res, a): + return res + a + + def sub(res, a): + return res - a + + def main_interpreter_loop(a): + i = 0 + res = 0 + c = len(code) + while True: + myjitdriver.jit_merge_point(res=res, i=i, a=a) + if i >= c: + break + elem = code[i] + if elem == CO_INCREASE: + i += a + res += a + else: + if res > 100: + i += 1 + else: + i = i - 3 + myjitdriver.can_enter_jit(res=res, i=i, a=a) + return res + + res = self.meta_interp(main_interpreter_loop, [1]) + assert res == main_interpreter_loop(1) + self.check_loop_count(1) + # XXX maybe later optimize guard_value away + self.check_loops({'merge_point' : 1, 'int_add' : 6, 'int_gt' : 1, + 'guard_false' : 1, 'jump' : 1, 'guard_value' : 3}) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Wed Feb 11 15:19:08 2009 @@ -285,49 +285,6 @@ self.check_loop_count(1) self.check_loops(int_add=0, int_mul=1, guard_class=0) - def test_example(self): - myjitdriver = JitDriver(greens = ['i'], - reds = ['res', 'a']) - CO_INCREASE = 0 - CO_JUMP_BACK_3 = 1 - CO_DECREASE = 2 - - code = [CO_INCREASE, CO_INCREASE, CO_INCREASE, - CO_JUMP_BACK_3, CO_INCREASE, CO_DECREASE] - - def add(res, a): - return res + a - - def sub(res, a): - return res - a - - def main_interpreter_loop(a): - i = 0 - res = 0 - c = len(code) - while i < c: - myjitdriver.jit_merge_point(res=res, i=i, a=a) - elem = code[i] - if elem == CO_INCREASE: - res = add(res, a) - elif elem == CO_DECREASE: - res = sub(res, a) - else: - if res > 100: - pass - else: - i = i - 3 - myjitdriver.can_enter_jit(res=res, i=i, a=a) - continue - i = i + 1 - return res - - res = self.meta_interp(main_interpreter_loop, [1]) - assert res == 102 - self.check_loop_count(1) - self.check_loops({'merge_point' : 1, 'int_add' : 3, 'int_gt' : 1, - 'guard_false' : 1, 'jump' : 1}) - class TestOOtype(SendTests, OOJitMixin): pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Wed Feb 11 15:19:08 2009 @@ -10,9 +10,11 @@ class TLCTests: def _get_interp(self, bytecode, pool): - def interp(inputarg): + codes = [bytecode, ''] + pools = [pool, None] + def interp(i, inputarg): args = [tlc.IntObj(inputarg)] - obj = tlc.interp_eval(bytecode, 0, args, pool) + obj = tlc.interp_eval(codes[i], 0, args, pools[i]) return obj.int_o() return interp @@ -20,7 +22,7 @@ pool = tlc.ConstantPool() bytecode = tlc.compile(src, pool) interp = self._get_interp(bytecode, pool) - return self.meta_interp(interp, [inputarg], view=False) + return self.meta_interp(interp, [0, inputarg], view=False) def test_method(self): code = """ @@ -42,7 +44,6 @@ assert res == 42 def test_accumulator(self): - py.test.skip("takes too long and does not optimize :-(") path = py.path.local(tlc.__file__).dirpath('accumulator.tlc.src') code = path.read() res = self.exec_code(code, 20) From fijal at codespeak.net Wed Feb 11 15:34:46 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 15:34:46 +0100 (CET) Subject: [pypy-svn] r61733 - in pypy/branch/pyjitpl5/pypy/jit/tl: . test Message-ID: <20090211143446.38867169EBB@codespeak.net> Author: fijal Date: Wed Feb 11 15:34:45 2009 New Revision: 61733 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlr.py pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Log: (arigo, fijal) A go at making tl use non-resizable stack Modified: pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tl.py Wed Feb 11 15:34:45 2009 @@ -1,7 +1,6 @@ import py import operator from pypy.jit.tl.tlopcode import * -from pypy.jit.conftest import Benchmark from pypy.translator.c.test import test_boehm from pypy.annotation import policy @@ -224,6 +223,7 @@ assert res == 720 def test_translate_factorial(self): + py.test.skip("?") # use py.test --benchmark to do the benchmarking code = compile(FACTORIAL_SOURCE) interp = self.interp Modified: pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlr.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlr.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlr.py Wed Feb 11 15:34:45 2009 @@ -1,5 +1,5 @@ +import py from pypy.jit.tl import tlr -from pypy.jit.conftest import Benchmark from pypy.translator.c.test import test_boehm @@ -12,6 +12,7 @@ assert tlr.interpret(tlr.SQUARE, 9) == 81 def test_translate(self): + py.test.skip("?") def driver(): bench = Benchmark() while 1: Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Wed Feb 11 15:34:45 2009 @@ -10,18 +10,32 @@ t = -(-ord(c) & 0xff) return t +class Stack(object): + def __init__(self, size): + self.stack = [0] * size + self.stackpos = 0 + + def append(self, elem): + self.stack[self.stackpos] = elem + self.stackpos += 1 + + def pop(self): + self.stackpos -= 1 + if self.stackpos < 0: + raise IndexError + return self.stack[self.stackpos] + def make_interp(supports_call): - myjitdriver = JitDriver(greens = ['pc', 'code', 'code_len'], + myjitdriver = JitDriver(greens = ['pc', 'code'], reds = ['stack', 'inputarg']) def interp(code='', pc=0, inputarg=0): if not isinstance(code,str): raise TypeError("code '%s' should be a string" % str(code)) - code_len = len(code) - stack = [] + stack = Stack(len(code)) - while pc < code_len: - myjitdriver.jit_merge_point(pc=pc, code=code, code_len=code_len, + while pc < len(code): + myjitdriver.jit_merge_point(pc=pc, code=code, stack=stack, inputarg=inputarg) opcode = ord(code[pc]) pc += 1 @@ -42,6 +56,7 @@ stack.append(b) elif opcode == ROLL: #rotate stack top to somewhere below + raise NotImplementedError("ROLL") r = char2int(code[pc]) if r < -1: i = len(stack) + r @@ -52,15 +67,17 @@ i = len(stack) - r if i < 0: raise IndexError - stack.append(stack.pop(i)) + stack.roll(i) pc += 1 elif opcode == PICK: + raise NotImplementedError("PICK") stack.append( stack[-1 - char2int(code[pc])] ) pc += 1 elif opcode == PUT: + raise NotImplementedError("PUT") stack[-1 - char2int(code[pc])] = stack.pop() pc += 1 @@ -108,7 +125,6 @@ if stack.pop(): pc += char2int(code[pc]) + 1 myjitdriver.can_enter_jit(pc=pc, code=code, - code_len=code_len, stack=stack, inputarg=inputarg) else: pc += 1 @@ -118,7 +134,6 @@ if stack.pop(): pc += offset myjitdriver.can_enter_jit(pc=pc, code=code, - code_len=code_len, stack=stack, inputarg=inputarg) elif supports_call and opcode == CALL: @@ -136,7 +151,7 @@ else: raise RuntimeError("unknown opcode: " + str(opcode)) - return stack[-1] + return stack.pop() return interp From arigo at codespeak.net Wed Feb 11 15:35:27 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 15:35:27 +0100 (CET) Subject: [pypy-svn] r61734 - pypy/branch/pyjitpl5/pypy/translator/c Message-ID: <20090211143527.5F35F169EBC@codespeak.net> Author: arigo Date: Wed Feb 11 15:35:26 2009 New Revision: 61734 Modified: pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py Log: (fijal, arigo) Another port from oo-jit. Modified: pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/c/funcgen.py Wed Feb 11 15:35:26 2009 @@ -772,4 +772,8 @@ def OP_IS_EARLY_CONSTANT(self, op): return self.expr(op.result) + ' = 0;' # Allways false + def OP_JIT_MARKER(self, op): + return '/* JIT_MARKER %s */' % op + + assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) From fijal at codespeak.net Wed Feb 11 15:47:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 15:47:42 +0100 (CET) Subject: [pypy-svn] r61735 - in pypy/branch/pyjitpl5/pypy/jit/tl: . test Message-ID: <20090211144742.477DB169EB5@codespeak.net> Author: fijal Date: Wed Feb 11 15:47:40 2009 New Revision: 61735 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Log: (arigo, fijal) Skip test_tlc and finish tl to be non resizable list Modified: pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tl.py Wed Feb 11 15:47:40 2009 @@ -101,6 +101,7 @@ assert self.interp(list2bytecode([PUSH,7, RETURN, PUSH,5])) == 7 def test_rot(self): + code = [PUSH,1, PUSH,2, PUSH,3, ROLL, 3] assert self.interp(list2bytecode(code)) == 1 assert self.interp(list2bytecode(code + [POP])) == 3 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlc.py Wed Feb 11 15:47:40 2009 @@ -1,4 +1,5 @@ import py +py.test.skip("Somehow broken") from pypy.jit.tl.tlopcode import compile, NEW, RETURN from pypy.jit.tl.test import test_tl from pypy.jit.tl.tlc import ConstantPool Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Wed Feb 11 15:47:40 2009 @@ -25,6 +25,32 @@ raise IndexError return self.stack[self.stackpos] + def pick(self, i): + self.append(self.stack[self.stackpos - i - 1]) + + def put(self, i): + elem = self.pop() + self.stack[self.stackpos - i - 1] = elem + + def roll(self, r): + if r < -1: + i = self.stackpos + r + if i < 0: + raise IndexError + elem = self.stack[self.stackpos - 1] + for j in range(self.stackpos - 2, i - 1, -1): + self.stack[j + 1] = self.stack[j] + self.stack[i] = elem + elif r > 1: + i = self.stackpos - r + if i < 0: + raise IndexError + elem = self.stack[i] + for j in range(i, self.stackpos - 1): + self.stack[j] = self.stack[j + 1] + self.stack[self.stackpos - 1] = elem + + def make_interp(supports_call): myjitdriver = JitDriver(greens = ['pc', 'code'], reds = ['stack', 'inputarg']) @@ -56,29 +82,16 @@ stack.append(b) elif opcode == ROLL: #rotate stack top to somewhere below - raise NotImplementedError("ROLL") r = char2int(code[pc]) - if r < -1: - i = len(stack) + r - if i < 0: - raise IndexError - stack.insert( i, stack.pop() ) - elif r > 1: - i = len(stack) - r - if i < 0: - raise IndexError - stack.roll(i) - + stack.roll(r) pc += 1 elif opcode == PICK: - raise NotImplementedError("PICK") - stack.append( stack[-1 - char2int(code[pc])] ) + stack.pick(char2int(code[pc])) pc += 1 elif opcode == PUT: - raise NotImplementedError("PUT") - stack[-1 - char2int(code[pc])] = stack.pop() + stack.put(char2int(code[pc])) pc += 1 elif opcode == ADD: From afa at codespeak.net Wed Feb 11 15:58:10 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Feb 2009 15:58:10 +0100 (CET) Subject: [pypy-svn] r61736 - in pypy/trunk/pypy: lib/app_test/ctypes_tests module/_rawffi module/_rawffi/test rlib Message-ID: <20090211145810.3041D169E3A@codespeak.net> Author: afa Date: Wed Feb 11 15:58:09 2009 New Revision: 61736 Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_loading.py pypy/trunk/pypy/module/_rawffi/interp_rawffi.py pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py pypy/trunk/pypy/rlib/libffi.py Log: Implement access to dll functions by ordinal. Now all ctypes tests pass on win32 :-) Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_loading.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_loading.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_loading.py Wed Feb 11 15:58:09 2009 @@ -61,8 +61,9 @@ WinDLL("coredll").GetModuleHandleW def test_load_ordinal_functions(self): - import _ctypes_test - dll = WinDLL(_ctypes_test.__file__) + import conftest + _ctypes_test = str(conftest.sofile) + dll = CDLL(_ctypes_test) # We load the same function both via ordinal and name func_ord = dll[2] func_name = dll.GetString Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Wed Feb 11 15:58:09 2009 @@ -142,7 +142,7 @@ self.w_cache = space.newdict() self.space = space - def ptr(self, space, name, w_argtypes, w_restype, flags=FUNCFLAG_CDECL): + def ptr(self, space, w_name, w_argtypes, w_restype, flags=FUNCFLAG_CDECL): """ Get a pointer for function name with provided argtypes and restype """ @@ -150,7 +150,7 @@ w = space.wrap argtypes_w = space.viewiterable(w_argtypes) w_argtypes = space.newtuple(argtypes_w) - w_key = space.newtuple([w(name), w_argtypes, w(resshape)]) + w_key = space.newtuple([w_name, w_argtypes, w(resshape)]) try: return space.getitem(self.w_cache, w_key) except OperationError, e: @@ -159,16 +159,34 @@ else: raise ffi_argtypes, argletters = unpack_argshapes(space, w_argtypes) - try: - ptr = self.cdll.getrawpointer(name, ffi_argtypes, ffi_restype, - flags) - w_funcptr = W_FuncPtr(space, ptr, argletters, resshape) - space.setitem(self.w_cache, w_key, w_funcptr) - return w_funcptr - except KeyError: - raise OperationError(space.w_AttributeError, space.wrap( - "No symbol %s found in library %s" % (name, self.name))) - ptr.unwrap_spec = ['self', ObjSpace, str, W_Root, W_Root, int] + + if space.is_true(space.isinstance(w_name, space.w_str)): + name = space.str_w(w_name) + + try: + ptr = self.cdll.getrawpointer(name, ffi_argtypes, ffi_restype, + flags) + except KeyError: + raise OperationError(space.w_AttributeError, space.wrap( + "No symbol %s found in library %s" % (name, self.name))) + + elif (_MS_WINDOWS and + space.is_true(space.isinstance(w_name, space.w_int))): + ordinal = space.int_w(w_name) + try: + ptr = self.cdll.getrawpointer_byordinal(ordinal, ffi_argtypes, + ffi_restype, flags) + except KeyError: + raise OperationError(space.w_AttributeError, space.wrap( + "No symbol %d found in library %s" % (ordinal, self.name))) + else: + raise OperationError(space.w_TypeError, space.wrap( + "function name must be string or integer")) + + w_funcptr = W_FuncPtr(space, ptr, argletters, resshape) + space.setitem(self.w_cache, w_key, w_funcptr) + return w_funcptr + ptr.unwrap_spec = ['self', ObjSpace, W_Root, W_Root, W_Root, int] def getaddressindll(self, space, name): try: Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Wed Feb 11 15:58:09 2009 @@ -140,6 +140,11 @@ inp.y *= 3; return inp; } + + int AAA_first_ordinal_function() + { + return 42; + } ''')) symbols = """get_char char_check get_raw_pointer @@ -153,6 +158,7 @@ static_int static_double sum_x_y give perturb + AAA_first_ordinal_function """.split() eci = ExternalCompilationInfo(export_symbols=symbols) return str(platform.compile([c_file], eci, 'x', standalone=False)) @@ -195,6 +201,16 @@ assert isinstance(func, _rawffi.FuncPtr) raises(AttributeError, "libc.xxxxxxxxxxxxxx") + def test_byordinal(self): + if not self.iswin32: + skip("win32 specific") + import _rawffi + lib = _rawffi.CDLL(self.lib_name) + # This will call the ordinal function numbered 1 + # my compiler seems to order them alphabetically: + # AAA_first_ordinal_function + assert lib.ptr(1, [], 'i')()[0] == 42 + def test_getchar(self): import _rawffi lib = _rawffi.CDLL(self.lib_name) Modified: pypy/trunk/pypy/rlib/libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/libffi.py (original) +++ pypy/trunk/pypy/rlib/libffi.py Wed Feb 11 15:58:09 2009 @@ -248,6 +248,10 @@ # XXX rffi.cast here... return res + def dlsym_byordinal(handle, index): + # Never called + raise KeyError(index) + libc_name = ctypes.util.find_library('c') if _WIN32: @@ -272,6 +276,15 @@ # XXX rffi.cast here... return res + def dlsym_byordinal(handle, index): + # equivalent to MAKEINTRESOURCEA + intresource = rffi.cast(rffi.CCHARP, r_uint(index) & 0xFFFF) + res = rwin32.GetProcAddress(handle, intresource) + if not res: + raise KeyError(name) + # XXX rffi.cast here... + return res + FormatError = rwin32.FormatError LoadLibrary = rwin32.LoadLibrary @@ -573,6 +586,13 @@ return RawFuncPtr(name, argtypes, restype, dlsym(self.lib, name), flags=flags) + def getrawpointer_byordinal(self, ordinal, argtypes, restype, + flags=FUNCFLAG_CDECL): + # these arguments are already casted to proper ffi + # structures! + return RawFuncPtr(name, argtypes, restype, + dlsym_byordinal(self.lib, ordinal), flags=flags) + def getaddressindll(self, name): return dlsym(self.lib, name) From fijal at codespeak.net Wed Feb 11 16:40:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 16:40:34 +0100 (CET) Subject: [pypy-svn] r61737 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090211154034.848E6169EDB@codespeak.net> Author: fijal Date: Wed Feb 11 16:40:30 2009 New Revision: 61737 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: (arigo, fijal) Fix a couple of bugs to pass most of test_virtual Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Wed Feb 11 16:40:30 2009 @@ -38,8 +38,12 @@ for key, value in self.fields.items(): if key not in other.fields: return False - if not value.equals(other.fields[key]): - return False + if value is None: + if other.fields[key] is not None: + return False + else: + if not value.equals(other.fields[key]): + return False return True def matches(self, instnode): @@ -48,7 +52,7 @@ for key, value in self.fields.items(): if key not in instnode.curfields: return False - if not value.matches(instnode.curfields[key]): + if value is not None and not value.matches(instnode.curfields[key]): return False return True @@ -151,10 +155,20 @@ return None return FixedClassSpecNode(known_class) fields = {} - for ofs, node in self.origfields.items(): - if ofs in other.curfields: - specnode = node.intersect(other.curfields[ofs]) + for ofs, node in other.curfields.items(): + if ofs in self.origfields: + specnode = self.origfields[ofs].intersect(node) fields[ofs] = specnode + else: + fields[ofs] = None + self.origfields[ofs] = InstanceNode(node.source.clonebox()) + +# for ofs, node in self.origfields.items(): +# if ofs in other.curfields: +# specnode = node.intersect(other.curfields[ofs]) +# fields[ofs] = specnode +# else: +# fields[ofs] = None return VirtualInstanceSpecNode(known_class, fields) def adapt_to(self, specnode): @@ -291,7 +305,8 @@ if isinstance(specnode, VirtualInstanceSpecNode): curfields = {} for ofs, subspecnode in specnode.fields.items(): - subinstnode = instnode.origfields[ofs] # should be there + subinstnode = instnode.origfields[ofs] + # should really be there self.mutate_nodes(subinstnode, subspecnode) curfields[ofs] = subinstnode instnode.curfields = curfields Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Feb 11 16:40:30 2009 @@ -1,45 +1,9 @@ import py -py.test.skip("look later") from pypy.rlib.jit import JitDriver, hint -from pypy.jit.hintannotator.policy import StopAtXPolicy -from pyjitpl import oo_meta_interp, get_stats -from test.test_basic import LLJitMixin, OOJitMixin +from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem import lltype, rclass - -from vinst import find_sorted_list -import heaptracker - - -##def test_heaptracker(): -## def f(): -## n = lltype.malloc(NODE) -## n.value = 42 -## return n -## res = oo_meta_interp(f, []) -## assert lltype.typeOf(res) is NODE -## assert res.value == 42 -## assert get_stats().heaptracker.known_unescaped(res) - -def test_find_sorted_list(): - assert find_sorted_list(5, []) == 0 - assert find_sorted_list(4, [(5,)]) == 0 - assert find_sorted_list(5, [(5,)]) == -1 - assert find_sorted_list(6, [(5,)]) == 1 - assert find_sorted_list(2, [(5,), (6,), (7,)]) == 0 - assert find_sorted_list(5.2, [(5,), (6,), (7,)]) == 1 - assert find_sorted_list(6.5, [(5,), (6,), (7,)]) == 2 - assert find_sorted_list(11, [(5,), (6,), (7,)]) == 3 - assert find_sorted_list(5, [(5,), (6,), (7,)]) == -3 - assert find_sorted_list(6, [(5,), (6,), (7,)]) == -2 - assert find_sorted_list(7, [(5,), (6,), (7,)]) == -1 - lst = [(j,) for j in range(1, 50, 2)] - for i in range(50): - res = find_sorted_list(i, lst) - if i % 2 == 0: - assert res == i // 2 - else: - assert res == (i // 2) - (50 // 2) - +from pypy.jit.metainterp import heaptracker class VirtualTests: def _freeze_(self): @@ -52,6 +16,7 @@ node.value = 0 node.extra = 0 while n > 0: + myjitdriver.can_enter_jit(n=n, node=node) myjitdriver.jit_merge_point(n=n, node=node) next = self._new() next.value = node.value + n @@ -60,12 +25,12 @@ n -= 1 return node.value * node.extra assert f(10) == 55 * 10 - res = self.meta_interp(f, [10], exceptions=False) + res = self.meta_interp(f, [10]) assert res == 55 * 10 - assert len(get_stats().loops) == 1 - get_stats().check_loops(new=0, new_with_vtable=0, - getfield_int=0, getfield_ptr=0, - setfield_int=0, setfield_ptr=0) + self.check_loop_count(1) + self.check_loops(new=0, new_with_vtable=0, + getfield_gc__4=0, getfield_gc_ptr=0, + setfield_gc__4=0, setfield_gc_ptr=0) def test_virtualized_2(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) @@ -74,6 +39,7 @@ node.value = 0 node.extra = 0 while n > 0: + myjitdriver.can_enter_jit(n=n, node=node) myjitdriver.jit_merge_point(n=n, node=node) next = self._new() next.value = node.value @@ -85,12 +51,12 @@ node = next n -= 1 return node.value * node.extra - res = self.meta_interp(f, [10], exceptions=False) + res = self.meta_interp(f, [10]) assert res == 55 * 30 - assert len(get_stats().loops) == 1 - get_stats().check_loops(new=0, new_with_vtable=0, - getfield_int=0, getfield_ptr=0, - setfield_int=0, setfield_ptr=0) + self.check_loop_count(1) + self.check_loops(new=0, new_with_vtable=0, + getfield_gc__4=0, getfield_gc_ptr=0, + setfield_gc__4=0, setfield_gc_ptr=0) def test_nonvirtual_obj_delays_loop(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) @@ -99,6 +65,7 @@ def f(n): node = node0 while True: + myjitdriver.can_enter_jit(n=n, node=node) myjitdriver.jit_merge_point(n=n, node=node) i = node.value if i >= n: @@ -106,17 +73,12 @@ node = self._new() node.value = i * 2 return node.value - res = self.meta_interp(f, [500], exceptions=False) + res = self.meta_interp(f, [500]) assert res == 640 - # The only way to make an efficient loop (in which the node is - # virtual) is to keep the first iteration out of the residual loop's - # body. Indeed, the initial value 'node0' cannot be passed inside - # the loop as a virtual. It's hard to test that this is what occurred, - # though. - assert len(get_stats().loops) == 1 - get_stats().check_loops(new=0, new_with_vtable=0, - getfield_int=0, getfield_ptr=0, - setfield_int=0, setfield_ptr=0) + self.check_loop_count(1) + self.check_loops(new=0, new_with_vtable=0, + getfield_gc__4=0, getfield_gc_ptr=0, + setfield_gc__4=0, setfield_gc_ptr=0) def test_two_loops_with_virtual(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) @@ -125,6 +87,7 @@ node.value = 0 node.extra = 0 while n > 0: + myjitdriver.can_enter_jit(n=n, node=node) myjitdriver.jit_merge_point(n=n, node=node) next = self._new() next.value = node.value + n @@ -135,12 +98,12 @@ node = next n -= 1 return node.value - res = self.meta_interp(f, [10], exceptions=False) + res = self.meta_interp(f, [10]) assert res == 255 - assert len(get_stats().loops) == 2 - get_stats().check_loops(new=0, new_with_vtable=0, - getfield_int=0, getfield_ptr=0, - setfield_int=0, setfield_ptr=0) + self.check_loop_count(2) + self.check_loops(new=0, new_with_vtable=0, + getfield_gc__4=0, getfield_gc_ptr=0, + setfield_gc__4=0, setfield_gc_ptr=0) def test_two_loops_with_escaping_virtual(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) @@ -151,6 +114,7 @@ node.value = 0 node.extra = 0 while n > 0: + myjitdriver.can_enter_jit(n=n, node=node) myjitdriver.jit_merge_point(n=n, node=node) next = self._new() next.value = node.value + n @@ -161,32 +125,14 @@ node = next n -= 1 return node.value - res = self.meta_interp(f, [10], policy=StopAtXPolicy(externfn), - exceptions=False) + res = self.meta_interp(f, [10], policy=StopAtXPolicy(externfn)) assert res == f(10) - assert len(get_stats().loops) == 2 - get_stats().check_loops(**{self._new_op: 1}) - get_stats().check_loops(int_mul=0, call__4=1) - - def test_virtual_if_unescaped_so_far(self): - class Foo(object): - def __init__(self, x, y): - self.x = x - self.y = y - - def f(n): - foo = Foo(n, 0) - while foo.x > 0: - foo.y += foo.x - foo.x -= 1 - return foo.y - - res = self.meta_interp(f, [10], exceptions=False) - assert res == 55 - py.test.skip("unsure yet if we want to be clever about this") - get_stats().check_loops(getfield_int=0, setfield_int=0) + self.check_loop_count(2) + self.check_loops(**{self._new_op: 1}) + self.check_loops(int_mul=0, call__4=1) def test_two_virtuals(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'prev']) class Foo(object): def __init__(self, x, y): self.x = x @@ -196,20 +142,26 @@ prev = Foo(n, 0) n -= 1 while n >= 0: + myjitdriver.can_enter_jit(n=n, prev=prev) + myjitdriver.jit_merge_point(n=n, prev=prev) foo = Foo(n, 0) foo.x += prev.x prev = foo n -= 1 return prev.x - res = self.meta_interp(f, [12], exceptions=False) + res = self.meta_interp(f, [12]) assert res == 78 + self.check_loops(new_with_vtable=0, new=0) def test_both_virtual_and_field_variable(self): + myjitdriver = JitDriver(greens = [], reds = ['n']) class Foo(object): pass def f(n): while n >= 0: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) foo = Foo() foo.n = n if n < 10: @@ -217,7 +169,7 @@ n = foo.n - 1 return n - res = self.meta_interp(f, [20], exceptions=False) + res = self.meta_interp(f, [20]) assert res == 9 From arigo at codespeak.net Wed Feb 11 16:42:39 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 16:42:39 +0100 (CET) Subject: [pypy-svn] r61738 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090211154239.B1DB9169EBC@codespeak.net> Author: arigo Date: Wed Feb 11 16:42:38 2009 New Revision: 61738 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: (fijal, arigo) Fix a dict order dependency bug. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Wed Feb 11 16:42:38 2009 @@ -326,7 +326,9 @@ if not instnode.virtual: newboxlist.append(instnode.source) return - for subinstnode in instnode.curfields.values(): + lst = instnode.curfields.items() + lst.sort() + for _, subinstnode in lst: self.expanded_version_of_rec(subinstnode, newboxlist, memo) def optimize_guard(self, op): From fijal at codespeak.net Wed Feb 11 16:45:04 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 16:45:04 +0100 (CET) Subject: [pypy-svn] r61739 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090211154504.BF9AD169E79@codespeak.net> Author: fijal Date: Wed Feb 11 16:45:04 2009 New Revision: 61739 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: (arigo, fijal) skip the test about non-objects Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Feb 11 16:45:04 2009 @@ -196,6 +196,10 @@ class TestLLtype_NotObject(VirtualTests, LLJitMixin): _new_op = 'new' + + def setup_class(cls): + py.test.skip("not supported yet") + @staticmethod def _new(): return lltype.malloc(NODE) From arigo at codespeak.net Wed Feb 11 17:06:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 17:06:00 +0100 (CET) Subject: [pypy-svn] r61740 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090211160600.A4EAA169E80@codespeak.net> Author: arigo Date: Wed Feb 11 17:06:00 2009 New Revision: 61740 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: (arigo, fijal) try to have the same args in jump and merge point Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Wed Feb 11 17:06:00 2009 @@ -313,23 +313,24 @@ instnode.virtual = True def expanded_version_of(self, boxlist): - memo = {} newboxlist = [] - for box in boxlist: - self.expanded_version_of_rec(self.nodes[box], newboxlist, memo) + assert len(boxlist) == len(self.specnodes) + for i in range(len(boxlist)): + box = boxlist[i] + specnode = self.specnodes[i] + self.expanded_version_of_rec(specnode, self.nodes[box], newboxlist) return newboxlist - def expanded_version_of_rec(self, instnode, newboxlist, memo): - if instnode in memo: - return - memo[instnode] = None - if not instnode.virtual: + def expanded_version_of_rec(self, specnode, instnode, newboxlist): + if not isinstance(specnode, VirtualInstanceSpecNode): newboxlist.append(instnode.source) - return - lst = instnode.curfields.items() - lst.sort() - for _, subinstnode in lst: - self.expanded_version_of_rec(subinstnode, newboxlist, memo) + else: + lst = specnode.fields.items() + lst.sort() + for ofs, subspecnode in lst: + subinstnode = instnode.curfields[ofs] # should really be there + self.expanded_version_of_rec(subspecnode, subinstnode, + newboxlist) def optimize_guard(self, op): liveboxes = [] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Wed Feb 11 17:06:00 2009 @@ -99,7 +99,7 @@ n -= 1 return node.value res = self.meta_interp(f, [10]) - assert res == 255 + assert res == f(10) self.check_loop_count(2) self.check_loops(new=0, new_with_vtable=0, getfield_gc__4=0, getfield_gc_ptr=0, From arigo at codespeak.net Wed Feb 11 17:16:51 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 17:16:51 +0100 (CET) Subject: [pypy-svn] r61741 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090211161651.3BCD7169EA1@codespeak.net> Author: arigo Date: Wed Feb 11 17:16:50 2009 New Revision: 61741 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: (fijal, arigo) Fix bug, second part. Argh. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Wed Feb 11 17:16:50 2009 @@ -99,7 +99,9 @@ if not isinstance(specnode, VirtualInstanceSpecNode): resultlist.append(valuebox) return - for ofs, subspecnode in specnode.fields.items(): + lst = specnode.fields.items() + lst.sort() + for ofs, subspecnode in lst: cls = specnode.known_class.getint() typemarker = type_cache.field_type[cls, ofs] if typemarker.startswith('_'): From arigo at codespeak.net Wed Feb 11 17:21:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 17:21:37 +0100 (CET) Subject: [pypy-svn] r61742 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090211162137.69243169E42@codespeak.net> Author: arigo Date: Wed Feb 11 17:21:36 2009 New Revision: 61742 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: (fijal, arigo) Store in VirtualInstanceSpecNode.fields a list instead of a dict, to save space :-) but really to avoid issues about dictionary order. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Wed Feb 11 17:21:36 2009 @@ -35,21 +35,23 @@ elif len(self.fields) != len(other.fields): return False else: - for key, value in self.fields.items(): - if key not in other.fields: + for i in range(len(self.fields)): + key, value = self.fields[i] + otherkey, othervalue = other.fields[i] + if key != otherkey: return False if value is None: - if other.fields[key] is not None: + if othervalue is not None: return False else: - if not value.equals(other.fields[key]): + if not value.equals(othervalue): return False return True def matches(self, instnode): if not FixedClassSpecNode.matches(self, instnode): return False - for key, value in self.fields.items(): + for key, value in self.fields: if key not in instnode.curfields: return False if value is not None and not value.matches(instnode.curfields[key]): @@ -99,9 +101,7 @@ if not isinstance(specnode, VirtualInstanceSpecNode): resultlist.append(valuebox) return - lst = specnode.fields.items() - lst.sort() - for ofs, subspecnode in lst: + for ofs, subspecnode in specnode.fields: cls = specnode.known_class.getint() typemarker = type_cache.field_type[cls, ofs] if typemarker.startswith('_'): @@ -156,28 +156,23 @@ if self.cls is None: return None return FixedClassSpecNode(known_class) - fields = {} - for ofs, node in other.curfields.items(): + fields = [] + lst = other.curfields.items() + lst.sort() + for ofs, node in lst: if ofs in self.origfields: specnode = self.origfields[ofs].intersect(node) - fields[ofs] = specnode else: - fields[ofs] = None self.origfields[ofs] = InstanceNode(node.source.clonebox()) - -# for ofs, node in self.origfields.items(): -# if ofs in other.curfields: -# specnode = node.intersect(other.curfields[ofs]) -# fields[ofs] = specnode -# else: -# fields[ofs] = None + specnode = None + fields.append((ofs, specnode)) return VirtualInstanceSpecNode(known_class, fields) def adapt_to(self, specnode): if not isinstance(specnode, VirtualInstanceSpecNode): self.escaped = True return - for ofs, subspecnode in specnode.fields.items(): + for ofs, subspecnode in specnode.fields: self.curfields[ofs].adapt_to(subspecnode) @@ -306,7 +301,7 @@ assert instnode.cls.source.equals(specnode.known_class) if isinstance(specnode, VirtualInstanceSpecNode): curfields = {} - for ofs, subspecnode in specnode.fields.items(): + for ofs, subspecnode in specnode.fields: subinstnode = instnode.origfields[ofs] # should really be there self.mutate_nodes(subinstnode, subspecnode) @@ -327,9 +322,7 @@ if not isinstance(specnode, VirtualInstanceSpecNode): newboxlist.append(instnode.source) else: - lst = specnode.fields.items() - lst.sort() - for ofs, subspecnode in lst: + for ofs, subspecnode in specnode.fields: subinstnode = instnode.curfields[ofs] # should really be there self.expanded_version_of_rec(subspecnode, subinstnode, newboxlist) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Wed Feb 11 17:21:36 2009 @@ -112,7 +112,7 @@ assert spec_sum is None # for now assert isinstance(spec_n, VirtualInstanceSpecNode) assert spec_n.known_class.value == node_vtable_adr - assert spec_n.fields == {A.ofs_value: None} + assert spec_n.fields == [(A.ofs_value, None)] def test_A_optimize_loop(): operations = A.ops[:] From fijal at codespeak.net Wed Feb 11 17:58:53 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 11 Feb 2009 17:58:53 +0100 (CET) Subject: [pypy-svn] r61744 - in pypy/branch/pyjitpl5/pypy: jit/backend/llgraph jit/metainterp jit/metainterp/test rlib rpython rpython/lltypesystem Message-ID: <20090211165853.931C5169EAD@codespeak.net> Author: fijal Date: Wed Feb 11 17:58:50 2009 New Revision: 61744 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py (contents, props changed) pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py - copied unchanged from r61379, pypy/branch/oo-jit/pypy/rpython/lltypesystem/rvirtualizable2.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/rlib/jit.py pypy/branch/pyjitpl5/pypy/rpython/llinterp.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py Log: (arigo, fijal) Port pieces from here and there to start supporting virtualizables Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Wed Feb 11 17:58:50 2009 @@ -80,6 +80,7 @@ 'guard_value' : (('int', 'int'), None), 'guard_class' : (('ptr', 'ptr'), None), 'guard_exception' : (('ptr',), None), + 'guard_nonvirtualized__4' : (('ptr', 'int'), None), 'newstr' : (('int',), 'ptr'), 'strlen' : (('ptr',), 'int'), 'strgetitem' : (('ptr', 'int'), 'int'), @@ -600,11 +601,11 @@ if value != expected_value: raise GuardFailed - def op_guard_nonvirtualized_int(self, value, for_accessing_field): + def op_guard_nonvirtualized__4(self, value, for_accessing_field): if heaptracker.cast_vable(value).vable_rti: raise GuardFailed # some other code is already in control - op_guard_nonvirtualized_ptr = op_guard_nonvirtualized_int + op_guard_nonvirtualized_ptr = op_guard_nonvirtualized__4 def op_guard_exception(self, expected_exception): expected_exception = llmemory.cast_adr_to_ptr( Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Wed Feb 11 17:58:50 2009 @@ -622,7 +622,7 @@ try: virtualizabledesc = metainterp._virtualizabledescs[TOPSTRUCT] except KeyError: - import virtualizable + from pypy.jit.metainterp import virtualizable virtualizabledesc = virtualizable.VirtualizableDesc( self.cpu, TOPSTRUCT) virtualizabledesc.hash = len(metainterp._virtualizabledescs) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Wed Feb 11 17:58:50 2009 @@ -21,20 +21,21 @@ else: return lltype.cast_primitive(EXPECTED_TYPE, x) -#def cast_vable(p): -# p = p.ptr._as_ptr() -# STRUCT = cast_vable_type(lltype.typeOf(p).TO) -# return lltype.cast_pointer(lltype.Ptr(STRUCT), p) - -#def cast_vable_type(STRUCT): -# assert STRUCT._hints.get('virtualizable2'), \ -# "not a virtualizable2: %r" % (p,) -# while True: -# _, PARENT = STRUCT._first_struct() -# if PARENT is None or not PARENT._hints.get('virtualizable2'): -# break -# STRUCT = PARENT -# return STRUCT +def cast_vable(p): + T = lltype.Ptr(lltype.typeOf(p._obj.container)) + p = lltype.cast_opaque_ptr(T, p) + STRUCT = cast_vable_type(T.TO) + return lltype.cast_pointer(lltype.Ptr(STRUCT), p) + +def cast_vable_type(STRUCT): + assert STRUCT._hints.get('virtualizable2'), \ + "not a virtualizable2: %r" % (p,) + while True: + _, PARENT = STRUCT._first_struct() + if PARENT is None or not PARENT._hints.get('virtualizable2'): + break + STRUCT = PARENT + return STRUCT def get_vtable_for_gcstruct(cpu, GCSTRUCT): # xxx hack: from a GcStruct representing an instance's Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Wed Feb 11 17:58:50 2009 @@ -666,6 +666,8 @@ self.builtins_keys = [] self.builtins_values = [] self.builtins_seen = {} + + self._virtualizabledescs = {} def generate_bytecode(self, policy): self._codewriter = codewriter.CodeWriter(self, policy) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Wed Feb 11 17:58:50 2009 @@ -1,24 +1,64 @@ import py -py.test.skip("XXX") from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR -from pypy.rpython.lltypesystem import lltype, lloperation +from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory from pypy.rpython.annlowlevel import llhelper -from pypy.jit.hintannotator.policy import StopAtXPolicy -from pypy.rlib.jit import hint -from pyjitpl import get_stats -from test.test_basic import LLJitMixin, OOJitMixin -from test.test_specnode_vable import XY +from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.rlib.jit import JitDriver +from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin +from pypy.jit.metainterp import heaptracker +from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR +from pypy.rpython.lltypesystem.rvirtualizable2 import VirtualizableAccessor promote_virtualizable = lloperation.llop.promote_virtualizable debug_print = lloperation.llop.debug_print + # ____________________________________________________________ -py.test.skip("XXX") +XY = lltype.GcStruct( + 'XY', + ('parent', rclass.OBJECT), + ('vable_base', llmemory.Address), + ('vable_rti', VABLERTIPTR), + ('x', lltype.Signed), + ('y', lltype.Signed), + hints = {'virtualizable2': True}, + adtmeths = {'access': VirtualizableAccessor()}) +XY._adtmeths['access'].initialize(XY, ['x', 'y']) + +xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) +xy_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 3, immortal=True) +xy_vtable.name[0] = 'X' +xy_vtable.name[1] = 'Y' +xy_vtable.name[2] = '\x00' +heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable) + +XYSUB = lltype.GcStruct( + 'XYSUB', + ('parent', XY), + ('z', lltype.Signed), + hints = {'virtualizable2': True}, + adtmeths = {'access': VirtualizableAccessor()}) +XYSUB._adtmeths['access'].initialize(XYSUB, ['z'], PARENT=XY) + +xysub_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) +xysub_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 6, + immortal=True) +xysub_vtable.name[0] = 'X' +xysub_vtable.name[1] = 'Y' +xysub_vtable.name[2] = 'S' +xysub_vtable.name[3] = 'U' +xysub_vtable.name[4] = 'B' +xysub_vtable.name[5] = '\x00' +heaptracker.set_testing_vtable_for_gcstruct(XYSUB, xysub_vtable) + +# ____________________________________________________________ class ExplicitVirtualizableTests: def test_preexisting_access(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], + virtualizables = ['xy']) def setup(): xy = lltype.malloc(XY) xy.vable_rti = lltype.nullptr(VABLERTIPTR.TO) @@ -27,12 +67,14 @@ xy = setup() xy.x = 10 while n > 0: + myjitdriver.can_enter_jit(xy=xy, n=n) + myjitdriver.jit_merge_point(xy=xy, n=n) promote_virtualizable(lltype.Void, xy, 'x') x = xy.x xy.x = x + 1 n -= 1 self.meta_interp(f, [5]) - self.check_loops(getfield__4=0, setfield__4=0) + self.check_loops(getfield_gc__4=0, setfield_gc__4=0) def test_preexisting_access_2(self): def setup(): Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Wed Feb 11 17:58:50 2009 @@ -0,0 +1,75 @@ + +from pypy.jit.metainterp import history +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.annlowlevel import llhelper + +class VirtualizableDesc(history.AbstractValue): + hash = 0 + + def __init__(self, cpu, TOPSTRUCT): + "NOT_RPYTHON" + initialize_virtualizable(cpu, TOPSTRUCT.access) + self.vable_base = cpu.offsetof(TOPSTRUCT, 'vable_base') + self.vable_rti = cpu.offsetof(TOPSTRUCT, 'vable_rti') + self.c_vable_base = history.ConstInt(self.vable_base) + self.c_vable_rti = history.ConstInt(self.vable_rti) + +def initialize_virtualizable(cpu, access): + if not hasattr(cpu, '_seen_virtualizables'): + cpu._seen_virtualizables = {} + if access in cpu._seen_virtualizables: + return + cpu._seen_virtualizables[access] = True + for fieldname in access.redirected_fields: + initialize_vable_field(cpu, access, fieldname) + for subaccess in access.subaccessors: + initialize_virtualizable(cpu, subaccess) + if access.parent is not None: + initialize_virtualizable(cpu, access.parent) + +def initialize_vable_field(cpu, access, fieldname): + FIELDTYPE = getattr(access.STRUCT, fieldname) + if FIELDTYPE is lltype.Void: + return + type = history.getkind_num(cpu, FIELDTYPE) + ofs = cpu.offsetof(access.STRUCT, fieldname) + getset = access.getsets[fieldname] + + def getter(instanceptr): + rti = instanceptr.vable_rti + if we_are_translated(): + rti = cast_base_ptr_to_instance(VirtualizableRTI, rti) + instanceptr = lltype.cast_opaque_ptr(llmemory.GCREF, instanceptr) + box = rti.get_field(instanceptr, ofs, type) + if type == 'ptr': + return box.getptr(RESTYPE) + else: + return lltype.cast_primitive(RESTYPE, box.getint()) + + def setter(instanceptr, value): + rti = instanceptr.vable_rti + if we_are_translated(): + rti = cast_base_ptr_to_instance(VirtualizableRTI, rti) + instanceadr = lltype.cast_opaque_ptr(llmemory.GCREF, instanceptr) + if type == 'ptr': + valuebox = BoxPtr(llmemory.cast_ptr_to_adr(value)) + else: + valuebox = BoxInt(lltype.cast_primitive(lltype.Signed, value)) + rti.set_field(instanceadr, ofs, type, valuebox) + + GETSET = lltype.typeOf(getset).TO + RESTYPE = GETSET.get.TO.RESULT + if cpu.translate_support_code: + mixlevelann = cpu.mixlevelann + getset.get = mixlevelann.delayedfunction(getter, + [lltype_to_annotation(t) for t in GETSET.get.TO.ARGS], + lltype_to_annotation(GETSET.get.TO.RESULT), + needtype=True) + getset.set = mixlevelann.delayedfunction(setter, + [lltype_to_annotation(t) for t in GETSET.set.TO.ARGS], + lltype_to_annotation(GETSET.set.TO.RESULT), + needtype=True) + else: + # for testing: when the cpu and the metainterp are not translated + getset.get = llhelper(GETSET.get, getter) + getset.set = llhelper(GETSET.set, setter) Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rlib/jit.py (original) +++ pypy/branch/pyjitpl5/pypy/rlib/jit.py Wed Feb 11 17:58:50 2009 @@ -90,13 +90,17 @@ will allow us (later) to support a single RPython program with several independent JITting interpreters in it. """ - def __init__(self, greens=None, reds=None): + def __init__(self, greens=None, reds=None, virtualizables=None): if greens is not None: self.greens = greens if reds is not None: self.reds = reds if not hasattr(self, 'greens') or not hasattr(self, 'reds'): raise AttributeError("no 'greens' or 'reds' supplied") + if virtualizables is not None: + self.virtualizables = virtualizables + for v in self.virtualizables: + assert v in self.reds self._alllivevars = dict.fromkeys(self.greens + self.reds) self._params = PARAMETERS.copy() if hasattr(self, 'on_enter_jit'): Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Wed Feb 11 17:58:50 2009 @@ -532,6 +532,9 @@ def op_jit_marker(self, *args): pass + def op_promote_virtualizable(self, object, fieldname): + pass # XXX should do something + def op_instrument_count(self, ll_tag, ll_label): pass # xxx for now Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py Wed Feb 11 17:58:50 2009 @@ -391,6 +391,7 @@ 'call_boehm_gc_alloc': LLOp(canraise=(MemoryError,)), 'jit_marker': LLOp(), + 'promote_virtualizable':LLOp(canrun=True), # __________ GC operations __________ Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py Wed Feb 11 17:58:50 2009 @@ -385,6 +385,9 @@ self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, ll_runtime_type_info, OBJECT, destrptr) + vtable = self.rclass.getvtable() + #self.rtyper.type_for_typeptr[vtable._obj] = self.lowleveltype.TO + def common_repr(self): # -> object or nongcobject reprs return getinstancerepr(self.rtyper, None, self.gcflavor) @@ -412,16 +415,17 @@ else: return self.rbase.get_ll_hash_function() - def initialize_prebuilt_data(self, value, classdef, result): + def initialize_prebuilt_instance(self, value, classdef, result): if self.classdef is not None: # recursively build the parent part of the instance - self.rbase.initialize_prebuilt_data(value, classdef, result.super) + self.rbase.initialize_prebuilt_instance(value, classdef, + result.super) # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): if r.lowleveltype is Void: llattrvalue = None elif name == '_hash_cache_': # hash() support - continue # already done by initialize_prebuilt_hash() + llattrvalue = hash(value) else: try: attrvalue = getattr(value, name) @@ -441,14 +445,6 @@ rclass = getclassrepr(self.rtyper, classdef) result.typeptr = rclass.getvtable() - def initialize_prebuilt_hash(self, value, result): - if self.classdef is not None: - self.rbase.initialize_prebuilt_hash(value, result.super) - if '_hash_cache_' in self.fields: - mangled_name, r = self.fields['_hash_cache_'] - llattrvalue = hash(value) - setattr(result, mangled_name, llattrvalue) - def getfieldrepr(self, attr): """Return the repr used for the given attribute.""" if attr in self.fields: @@ -606,17 +602,25 @@ if classdef is None: unboxed = [] virtualizable = False + virtualizable2 = False else: unboxed = [subdef for subdef in classdef.getallsubdefs() if subdef.classdesc.pyobj is not None and issubclass(subdef.classdesc.pyobj, UnboxedValue)] virtualizable = classdef.classdesc.read_attribute('_virtualizable_', Constant(False)).value + virtualizable2 = classdef.classdesc.read_attribute('_virtualizable2_', + Constant(False)).value if virtualizable: assert len(unboxed) == 0 assert gcflavor == 'gc' from pypy.rpython.lltypesystem import rvirtualizable return rvirtualizable.VirtualizableInstanceRepr(rtyper, classdef) + elif virtualizable2: + assert len(unboxed) == 0 + assert gcflavor == 'gc' + from pypy.rpython.lltypesystem import rvirtualizable2 + return rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef) elif len(unboxed) == 0: return InstanceRepr(rtyper, classdef, gcflavor) else: From getxsick at codespeak.net Wed Feb 11 18:34:45 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Wed, 11 Feb 2009 18:34:45 +0100 (CET) Subject: [pypy-svn] r61745 - pypy/trunk/pypy/interpreter/test Message-ID: <20090211173445.F3C81169E80@codespeak.net> Author: getxsick Date: Wed Feb 11 18:34:43 2009 New Revision: 61745 Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py Log: (jlg, getxsick) test for dis STOP_CODE insertion Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_compiler.py (original) +++ pypy/trunk/pypy/interpreter/test/test_compiler.py Wed Feb 11 18:34:43 2009 @@ -819,6 +819,27 @@ asm = dis_single('a="x"*1000') assert '(1000)' in asm + def test_dis_stopcode(self): + skip("not fixed yet") + source = """def _f(a): + print a + return 1 + """ + + exec source + code = _f.func_code + + import StringIO, sys, dis + s = StringIO.StringIO() + save_stdout = sys.stdout + sys.stdout = s + try: + dis.dis(code) + finally: + sys.stdout = save_stdout + output = s.getvalue() + assert "STOP_CODE" not in output + class AppTestExceptions: def test_indentation_error(self): source = """if 1: From arigo at codespeak.net Wed Feb 11 19:04:25 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 19:04:25 +0100 (CET) Subject: [pypy-svn] r61746 - in pypy/trunk/pypy/interpreter: astcompiler test Message-ID: <20090211180425.BF8FE169E8D@codespeak.net> Author: arigo Date: Wed Feb 11 19:04:24 2009 New Revision: 61746 Modified: pypy/trunk/pypy/interpreter/astcompiler/pyassem.py pypy/trunk/pypy/interpreter/test/test_compiler.py Log: (getxsick, arigo) Fix the handling of self.deadcode in pyassem. Fixes a failing test showing nonsense in dead parts of bytecodes. Modified: pypy/trunk/pypy/interpreter/astcompiler/pyassem.py ============================================================================== --- pypy/trunk/pypy/interpreter/astcompiler/pyassem.py (original) +++ pypy/trunk/pypy/interpreter/astcompiler/pyassem.py Wed Feb 11 19:04:24 2009 @@ -84,9 +84,10 @@ def emitop_extended_arg(self, intval): assert intval <= 0x7FFFFFFF - self.emit('EXTENDED_ARG') - self.co_code.append(chr((intval >> 16) & 0xFF)) - self.co_code.append(chr((intval >> 24) & 0xFF)) + if not self.deadcode: + self.emit('EXTENDED_ARG') + self.co_code.append(chr((intval >> 16) & 0xFF)) + self.co_code.append(chr((intval >> 24) & 0xFF)) return intval & 0xFFFF emitop_extended_arg._dont_inline_ = True @@ -102,11 +103,12 @@ if opname == "SET_LINENO": self.emitop_setlineno(intval) return - if intval > 0xFFFF: - intval = self.emitop_extended_arg(intval) - self.emit(opname) - self.co_code.append(chr(intval & 0xFF)) - self.co_code.append(chr(intval >> 8)) + if not self.deadcode: + if intval > 0xFFFF: + intval = self.emitop_extended_arg(intval) + self.emit(opname) + self.co_code.append(chr(intval & 0xFF)) + self.co_code.append(chr(intval >> 8)) # ____________________________________________________________ # Instructions with an object argument (LOAD_CONST) Modified: pypy/trunk/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_compiler.py (original) +++ pypy/trunk/pypy/interpreter/test/test_compiler.py Wed Feb 11 19:04:24 2009 @@ -820,7 +820,6 @@ assert '(1000)' in asm def test_dis_stopcode(self): - skip("not fixed yet") source = """def _f(a): print a return 1 From arigo at codespeak.net Wed Feb 11 19:07:52 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 19:07:52 +0100 (CET) Subject: [pypy-svn] r61747 - pypy/trunk/pypy/annotation/test Message-ID: <20090211180752.28CDE169E98@codespeak.net> Author: arigo Date: Wed Feb 11 19:07:51 2009 New Revision: 61747 Modified: pypy/trunk/pypy/annotation/test/test_annrpython.py Log: This test is not supported any more (more thinking needed). Modified: pypy/trunk/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/trunk/pypy/annotation/test/test_annrpython.py (original) +++ pypy/trunk/pypy/annotation/test/test_annrpython.py Wed Feb 11 19:07:51 2009 @@ -2761,6 +2761,7 @@ assert isinstance(s, annmodel.SomeExternalInstance) def test_instance_with_flags(self): + py.test.skip("not supported any more") from pypy.rlib.jit import hint class A: From arigo at codespeak.net Wed Feb 11 19:09:14 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 11 Feb 2009 19:09:14 +0100 (CET) Subject: [pypy-svn] r61749 - pypy/trunk/pypy/rpython/lltypesystem/test Message-ID: <20090211180914.75E33169E98@codespeak.net> Author: arigo Date: Wed Feb 11 19:09:14 2009 New Revision: 61749 Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rvirtualizable.py Log: Skip this test too for now on trunk. Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rvirtualizable.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_rvirtualizable.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_rvirtualizable.py Wed Feb 11 19:09:14 2009 @@ -1,4 +1,5 @@ import py +py.test.skip("see svn/pypy/branch/pyjitpl5") from pypy.objspace.flow.model import summary from pypy.rlib.jit import hint from pypy.rpython.lltypesystem import lltype, rclass From afa at codespeak.net Wed Feb 11 19:16:10 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Feb 2009 19:16:10 +0100 (CET) Subject: [pypy-svn] r61751 - pypy/trunk/pypy/lib/_ctypes Message-ID: <20090211181610.42926169E98@codespeak.net> Author: afa Date: Wed Feb 11 19:16:09 2009 New Revision: 61751 Modified: pypy/trunk/pypy/lib/_ctypes/__init__.py pypy/trunk/pypy/lib/_ctypes/basics.py Log: Add the simple _ctypes.COMError exception. Not yet used, except by a test. Modified: pypy/trunk/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/__init__.py (original) +++ pypy/trunk/pypy/lib/_ctypes/__init__.py Wed Feb 11 19:16:09 2009 @@ -1,6 +1,6 @@ from _ctypes.dummy import resize from _ctypes.basics import _CData, sizeof, alignment, byref, addressof,\ - ArgumentError + ArgumentError, COMError from _ctypes.primitive import _SimpleCData from _ctypes.pointer import _Pointer, _cast_addr from _ctypes.function import CFuncPtr Modified: pypy/trunk/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/basics.py (original) +++ pypy/trunk/pypy/lib/_ctypes/basics.py Wed Feb 11 19:16:09 2009 @@ -26,6 +26,14 @@ class ArgumentError(Exception): pass +class COMError(Exception): + "Raised when a COM method call failed." + def __init__(self, hresult, text, details): + self.args = (hresult, text, details) + self.hresult = hresult + self.text = text + self.details = details + class _CDataMeta(type): def from_param(self, value): if isinstance(value, self): From afa at codespeak.net Wed Feb 11 23:51:38 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 11 Feb 2009 23:51:38 +0100 (CET) Subject: [pypy-svn] r61759 - pypy/trunk/pypy/module/_rawffi Message-ID: <20090211225138.BDFA1169E4E@codespeak.net> Author: afa Date: Wed Feb 11 23:51:36 2009 New Revision: 61759 Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Log: Remove the 'v' letter type in _rawffi. It used to represent a void value, but this is not actually used by _rawffi. And 'v' is already used by the ctypes.wintypes.VARIANT_BOOL type on Windows. (I plan to add it shortly) Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Wed Feb 11 23:51:36 2009 @@ -68,7 +68,6 @@ 'Z' : rffi.CArrayPtr(lltype.UniChar), 'O' : rffi.VOIDP, 'P' : rffi.VOIDP, - 'v' : lltype.Void, } def letter2tp(space, key): @@ -85,12 +84,10 @@ raise OperationError(space.w_ValueError, space.wrap( "Unknown type letter %s" % (key,))) -def unpack_to_ffi_type(space, w_shape, allow_void=False, shape=False): +def unpack_to_ffi_type(space, w_shape, shape=False): resshape = None if space.is_true(space.isinstance(w_shape, space.w_str)): letter = space.str_w(w_shape) - if allow_void and letter == 'v': - return 'v', ffi_type_void, None ffi_type = _get_type_(space, letter) if shape: from pypy.module._rawffi.array import get_array_cache @@ -122,7 +119,6 @@ else: tp_letter, ffi_restype, resshape = unpack_to_ffi_type(space, w_restype, - allow_void=True, shape=True) return ffi_restype, resshape @@ -344,9 +340,6 @@ if c in TYPEMAP_PTR_LETTERS: res = func(add_arg, argdesc, rffi.VOIDP) return space.wrap(rffi.cast(lltype.Unsigned, res)) - elif c == 'v': - func(add_arg, argdesc, ll_type) - return space.w_None elif c == 'q' or c == 'Q' or c == 'L' or c == 'c' or c == 'u': return space.wrap(func(add_arg, argdesc, ll_type)) elif c == 'f' or c == 'd': From afa at codespeak.net Thu Feb 12 00:03:15 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 12 Feb 2009 00:03:15 +0100 (CET) Subject: [pypy-svn] r61761 - in pypy/trunk/pypy: lib/_ctypes module/_rawffi Message-ID: <20090211230315.383DC168576@codespeak.net> Author: afa Date: Thu Feb 12 00:03:14 2009 New Revision: 61761 Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Log: On windows, add the 'X' (BSTR) and 'v' (vBOOL) primitive types. Now "import ctype.wintypes" works Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/primitive.py (original) +++ pypy/trunk/pypy/lib/_ctypes/primitive.py Thu Feb 12 00:03:14 2009 @@ -1,5 +1,6 @@ import _rawffi import weakref +import sys SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" @@ -32,7 +33,11 @@ 'z': None, 'Z': None, } - + +if sys.platform == 'win32': + TP_TO_DEFAULT['X'] = NULL + TP_TO_DEFAULT['v'] = 0 + DEFAULT_VALUE = object() class GlobalPyobjContainer(object): Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Thu Feb 12 00:03:14 2009 @@ -42,6 +42,11 @@ } TYPEMAP_PTR_LETTERS = "POszZ" +if _MS_WINDOWS: + TYPEMAP['X'] = ffi_type_pointer + TYPEMAP['v'] = ffi_type_sshort + TYPEMAP_PTR_LETTERS += 'X' + def size_alignment(ffi_type): return intmask(ffi_type.c_size), intmask(ffi_type.c_alignment) From afa at codespeak.net Thu Feb 12 09:39:06 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 12 Feb 2009 09:39:06 +0100 (CET) Subject: [pypy-svn] r61767 - in pypy/trunk/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20090212083906.3D9C4169E42@codespeak.net> Author: afa Date: Thu Feb 12 09:39:05 2009 New Revision: 61767 Modified: pypy/trunk/pypy/lib/_ctypes/function.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py Log: Don't store the function ptr if the argtypes were guessed from the actual call. Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Thu Feb 12 09:39:05 2009 @@ -145,9 +145,11 @@ argshapes = [arg._ffiargshape for arg in argtypes] resshape = restype._ffiargshape if self._buffer is not None: - self._ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape, - self._flags_) - return self._ptr + ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape, + self._flags_) + if argtypes is self._argtypes_: + self._ptr = ptr + return ptr cdll = self.dll._handle try: Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py Thu Feb 12 09:39:05 2009 @@ -186,3 +186,19 @@ func.argtypes = (Adapter(),) # ArgumentError: argument 1: ValueError: 99 raises(ArgumentError, func, 99) + + def test_multiple_signature(self): + # when .argtypes is not set, calling a function with a certain + # set of parameters should not prevent another call with + # another set. + from ctypes import CDLL, byref + import conftest + dll = CDLL(str(conftest.sofile)) + func = dll._testfunc_p_p + + # This is call has too many arguments + assert func(None, 1) == 0 + + # This one is normal + assert func(None) == 0 + From afa at codespeak.net Thu Feb 12 10:10:58 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 12 Feb 2009 10:10:58 +0100 (CET) Subject: [pypy-svn] r61769 - in pypy/trunk/pypy: lib/app_test/ctypes_tests module/_rawffi module/_rawffi/test rlib Message-ID: <20090212091058.E2506169E15@codespeak.net> Author: afa Date: Thu Feb 12 10:10:58 2009 New Revision: 61769 Added: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_win32.py Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py pypy/trunk/pypy/rlib/libffi.py Log: On Windows, when using the STDCALL calling convention, the libffi library (at least, the version shipped with pypy and cpython) has the nice property to detect mismatches between the passed arguments and the ones expected by the function. This is possible because with STDCALL, the callee is responsible for cleaning the stack. Also adapt and add a win32-specific ctypes test file. (there are 5 more missing files in cpython test suite) Added: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_win32.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_win32.py Thu Feb 12 10:10:58 2009 @@ -0,0 +1,73 @@ +# Windows specific tests + +from ctypes import * +from ctypes.test import is_resource_enabled +from support import BaseCTypesTestChecker + +import py +import sys + +if sys.platform != "win32": + py.test.skip("win32-only tests") + +class TestWindows(BaseCTypesTestChecker): + def test_callconv_1(self): + # Testing stdcall function + + IsWindow = windll.user32.IsWindow + # ValueError: Procedure probably called with not enough arguments (4 bytes missing) + py.test.raises(ValueError, IsWindow) + + # This one should succeeed... + assert IsWindow(0) == 0 + + # ValueError: Procedure probably called with too many arguments (8 bytes in excess) + py.test.raises(ValueError, IsWindow, 0, 0, 0) + + def test_callconv_2(self): + # Calling stdcall function as cdecl + + IsWindow = cdll.user32.IsWindow + + # ValueError: Procedure called with not enough arguments (4 bytes missing) + # or wrong calling convention + py.test.raises(ValueError, IsWindow, None) + + if is_resource_enabled("SEH"): + def test_SEH(self): + # Call functions with invalid arguments, and make sure that access violations + # are trapped and raise an exception. + py.test.raises(WindowsError, windll.kernel32.GetModuleHandleA, 32) + +class TestWintypes(BaseCTypesTestChecker): + + def test_COMError(self): + import _ctypes + from _ctypes import COMError + assert COMError.__doc__ == "Raised when a COM method call failed." + + ex = COMError(-1, "text", ("details",)) + assert ex.hresult == -1 + assert ex.text == "text" + assert ex.details == ("details",) + assert (ex.hresult, ex.text, ex.details) == ex[:] + +class TestStructures(BaseCTypesTestChecker): + + def test_struct_by_value(self): + class POINT(Structure): + _fields_ = [("x", c_long), + ("y", c_long)] + + class RECT(Structure): + _fields_ = [("left", c_long), + ("top", c_long), + ("right", c_long), + ("bottom", c_long)] + + import conftest + dll = CDLL(str(conftest.sofile)) + + pt = POINT(10, 10) + rect = RECT(0, 0, 20, 20) + assert dll.PointInRect(byref(rect), pt) == 1 Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Thu Feb 12 10:10:58 2009 @@ -386,7 +386,7 @@ from pypy.module._rawffi.structure import W_StructureInstance argnum = len(args_w) if argnum != len(self.argletters): - msg = "Wrong number of argument: expected %d, got %d" % ( + msg = "Wrong number of arguments: expected %d, got %d" % ( len(self.argletters), argnum) raise OperationError(space.w_TypeError, space.wrap(msg)) args_ll = [] @@ -419,13 +419,17 @@ raise OperationError(space.w_TypeError, space.wrap(msg)) args_ll.append(arg.ll_buffer) # XXX we could avoid the intermediate list args_ll - if self.resshape is not None: - result = self.resshape.allocate(space, 1, autofree=True) - self.ptr.call(args_ll, result.ll_buffer) - return space.wrap(result) - else: - self.ptr.call(args_ll, lltype.nullptr(rffi.VOIDP.TO)) - return space.w_None + + try: + if self.resshape is not None: + result = self.resshape.allocate(space, 1, autofree=True) + self.ptr.call(args_ll, result.ll_buffer) + return space.wrap(result) + else: + self.ptr.call(args_ll, lltype.nullptr(rffi.VOIDP.TO)) + return space.w_None + except StackCheckError, e: + raise OperationError(space.w_ValueError, space.wrap(e.message)) call.unwrap_spec = ['self', ObjSpace, 'args_w'] def descr_new_funcptr(space, w_tp, addr, w_args, w_res, flags=FUNCFLAG_CDECL): Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Thu Feb 12 10:10:58 2009 @@ -752,8 +752,35 @@ raises(_rawffi.SegfaultException, a.__getitem__, 3) raises(_rawffi.SegfaultException, a.__setitem__, 3, 3) - def test_struct_byvalue(self): + def test_stackcheck(self): + if not self.iswin32: + skip("win32 specific") + + # Even if the call corresponds to the specified signature, + # the STDCALL calling convention may detect some errors import _rawffi + lib = _rawffi.CDLL('kernel32') + + f = lib.ptr('SetLastError', [], 'i') + try: + f() + except ValueError, e: + assert "Procedure called with not enough arguments" in e.message + else: + assert 0, "Did not raise" + + f = lib.ptr('GetLastError', ['i'], None, + flags=_rawffi.FUNCFLAG_STDCALL) + arg = _rawffi.Array('i')(1) + arg[0] = 1 + try: + f(arg) + except ValueError, e: + assert "Procedure called with too many arguments" in e.message + else: + assert 0, "Did not raise" + + def test_struct_byvalue(self): if self.isx86_64: skip("Segfaults on x86_64 because small structures " "may be passed in registers and " Modified: pypy/trunk/pypy/rlib/libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/libffi.py (original) +++ pypy/trunk/pypy/rlib/libffi.py Thu Feb 12 10:10:58 2009 @@ -251,6 +251,9 @@ def dlsym_byordinal(handle, index): # Never called raise KeyError(index) + + def check_fficall_result(result, flags): + pass # No check libc_name = ctypes.util.find_library('c') @@ -285,6 +288,27 @@ # XXX rffi.cast here... return res + def check_fficall_result(result, flags): + if result == 0: + return + # if win64: + # raises ValueError("ffi_call failed with code %d" % (result,)) + if result < 0: + if flags & FUNCFLAG_CDECL: + raise StackCheckError( + "Procedure called with not enough arguments" + " (%d bytes missing)" + " or wrong calling convention" % (-result,)) + else: + raise StackCheckError( + "Procedure called with not enough arguments " + " (%d bytes missing) " % (-result,)) + else: + raise StackCheckError( + "Procedure called with too many " + "arguments (%d bytes in excess) " % (result,)) + + FormatError = rwin32.FormatError LoadLibrary = rwin32.LoadLibrary @@ -309,8 +333,12 @@ c_ffi_prep_cif = external('ffi_prep_cif', [FFI_CIFP, rffi.USHORT, rffi.UINT, FFI_TYPE_P, FFI_TYPE_PP], rffi.INT) +if _WIN32: + c_ffi_call_return_type = rffi.INT +else: + c_ffi_call_return_type = lltype.Void c_ffi_call = external('ffi_call', [FFI_CIFP, rffi.VOIDP, rffi.VOIDP, - VOIDPP], lltype.Void) + VOIDPP], c_ffi_call_return_type) CALLBACK_TP = rffi.CCallback([FFI_CIFP, rffi.VOIDP, rffi.VOIDPP, rffi.VOIDP], lltype.Void) c_ffi_prep_closure = external('ffi_prep_closure', [FFI_CLOSUREP, FFI_CIFP, @@ -362,6 +390,10 @@ userdata = rffi.cast(USERDATA_P, ll_userdata) userdata.callback(ll_args, ll_res, userdata) +class StackCheckError(ValueError): + def __init__(self, message): + self.message = message + CHUNK = 4096 CLOSURES = rffi.CArrayPtr(FFI_CLOSUREP.TO) @@ -403,6 +435,7 @@ self.name = name self.argtypes = argtypes self.restype = restype + self.flags = flags argnum = len(argtypes) self.ll_argtypes = lltype.malloc(FFI_TYPE_PP.TO, argnum, flavor='raw') for i in range(argnum): @@ -481,8 +514,9 @@ for i in range(len(args_ll)): assert args_ll[i] # none should be NULL ll_args[i] = args_ll[i] - c_ffi_call(self.ll_cif, self.funcsym, ll_result, ll_args) + ffires = c_ffi_call(self.ll_cif, self.funcsym, ll_result, ll_args) lltype.free(ll_args, flavor='raw') + check_fficall_result(ffires, self.flags) class FuncPtr(AbstractFuncPtr): @@ -508,7 +542,7 @@ def push_arg(self, value): if self.pushed_args == self.argnum: - raise TypeError("Too much arguments, eats %d, pushed %d" % + raise TypeError("Too many arguments, eats %d, pushed %d" % (self.argnum, self.argnum + 1)) if not we_are_translated(): TP = lltype.typeOf(value) @@ -536,15 +570,16 @@ def call(self, RES_TP): self._check_args() - c_ffi_call(self.ll_cif, self.funcsym, - rffi.cast(rffi.VOIDP, self.ll_result), - rffi.cast(VOIDPP, self.ll_args)) + ffires = c_ffi_call(self.ll_cif, self.funcsym, + rffi.cast(rffi.VOIDP, self.ll_result), + rffi.cast(VOIDPP, self.ll_args)) if RES_TP is not lltype.Void: TP = lltype.Ptr(rffi.CArray(RES_TP)) res = rffi.cast(TP, self.ll_result)[0] else: res = None self._clean_args() + check_fficall_result(ffires, self.flags) return res call._annspecialcase_ = 'specialize:arg(1)' From getxsick at codespeak.net Thu Feb 12 11:03:48 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Thu, 12 Feb 2009 11:03:48 +0100 (CET) Subject: [pypy-svn] r61771 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090212100348.0AA7F169E51@codespeak.net> Author: getxsick Date: Thu Feb 12 11:03:47 2009 New Revision: 61771 Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py Log: update expected output Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py Thu Feb 12 11:03:47 2009 @@ -29,8 +29,6 @@ %-4d 5 LOAD_CONST 1 (1) 8 RETURN_VALUE - 9 LOAD_CONST 0 (None) - 12 RETURN_VALUE """%(_f.func_code.co_firstlineno + 1, _f.func_code.co_firstlineno + 2) From afa at codespeak.net Thu Feb 12 11:14:28 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 12 Feb 2009 11:14:28 +0100 (CET) Subject: [pypy-svn] r61772 - in pypy/trunk/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20090212101428.14EF2169E44@codespeak.net> Author: afa Date: Thu Feb 12 11:14:28 2009 New Revision: 61772 Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py Log: Don't ignore the from_param() defined in subclasses One more test passes Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/primitive.py (original) +++ pypy/trunk/pypy/lib/_ctypes/primitive.py Thu Feb 12 11:14:28 2009 @@ -7,6 +7,8 @@ from _ctypes.basics import _CData, _CDataMeta, cdata_from_address,\ CArgObject from _ctypes.builtin import ConvMode +from _ctypes.array import Array +from _ctypes.pointer import _Pointer class NULL(object): pass @@ -54,17 +56,43 @@ pyobj_container = GlobalPyobjContainer() -def generic_xxx_p_from_param(self, value): +def generic_xxx_p_from_param(cls, value): from _ctypes import Array, _Pointer if value is None: - return self(None) + return cls(None) if isinstance(value, basestring): - return self(value) + return cls(value) if isinstance(value, _SimpleCData) and \ type(value)._type_ in 'zZP': return value return None # eventually raise +def from_param_char_p(cls, value): + "used by c_char_p and c_wchar_p subclasses" + res = generic_xxx_p_from_param(cls, value) + if res is not None: + return res + if isinstance(value, (Array, _Pointer)): + from ctypes import c_char, c_byte, c_wchar + if type(value)._type_ in [c_char, c_byte, c_wchar]: + return value + +def from_param_void_p(cls, value): + "used by c_void_p subclasses" + res = generic_xxx_p_from_param(cls, value) + if res is not None: + return res + if isinstance(value, Array): + return value + if isinstance(value, _Pointer): + return cls.from_address(value._buffer.buffer) + +FROM_PARAM_BY_TYPE = { + 'z': from_param_char_p, + 'Z': from_param_char_p, + 'P': from_param_void_p, + } + class SimpleType(_CDataMeta): def __new__(self, name, bases, dct): try: @@ -154,33 +182,6 @@ self._buffer[0] = value result.value = property(_getvalue, _setvalue) - if tp in 'zZ': - from _ctypes import Array, _Pointer - # c_char_p - def from_param(self, value): - res = generic_xxx_p_from_param(self, value) - if res is not None: - return res - if isinstance(value, (Array, _Pointer)): - from ctypes import c_char, c_byte, c_wchar - if type(value)._type_ in [c_char, c_byte, c_wchar]: - return value - return SimpleType.from_param(self, value) - result.from_param = classmethod(from_param) - elif tp == 'P': - from _ctypes import Array, _Pointer - # c_void_p - def from_param(self, value): - res = generic_xxx_p_from_param(self, value) - if res is not None: - return res - if isinstance(value, Array): - return value - if isinstance(value, _Pointer): - return self.from_address(value._buffer.buffer) - return SimpleType.from_param(self, value) - result.from_param = classmethod(from_param) - elif tp == 'u': def _setvalue(self, val): if isinstance(val, str): @@ -215,6 +216,12 @@ from_address = cdata_from_address def from_param(self, value): + from_param_f = FROM_PARAM_BY_TYPE.get(self._type_) + if from_param_f: + res = from_param_f(self, value) + if res is not None: + return res + if isinstance(value, self): return value try: Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py Thu Feb 12 11:14:28 2009 @@ -22,7 +22,6 @@ def test_subclasses(self): - py.test.skip("subclassing semantics not implemented") from ctypes import c_void_p, c_char_p # ctypes 0.9.5 and before did overwrite from_param in SimpleType_new class CVOIDP(c_void_p): From getxsick at codespeak.net Thu Feb 12 12:02:26 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Thu, 12 Feb 2009 12:02:26 +0100 (CET) Subject: [pypy-svn] r61773 - pypy/trunk/lib-python/modified-2.5.2/test Message-ID: <20090212110226.239DE169E31@codespeak.net> Author: getxsick Date: Thu Feb 12 12:02:25 2009 New Revision: 61773 Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py Log: (jlg, getxsick) remove unnecessary difference between cpython and pypy test Modified: pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py ============================================================================== --- pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py (original) +++ pypy/trunk/lib-python/modified-2.5.2/test/test_dis.py Thu Feb 12 12:02:25 2009 @@ -12,7 +12,7 @@ print a return 1 -dis_f_cpy = """\ +dis_f = """\ %-4d 0 LOAD_FAST 0 (a) 3 PRINT_ITEM 4 PRINT_NEWLINE @@ -22,17 +22,6 @@ """%(_f.func_code.co_firstlineno + 1, _f.func_code.co_firstlineno + 2) -dis_f_pypy = """\ - %-4d 0 LOAD_FAST 0 (a) - 3 PRINT_ITEM - 4 PRINT_NEWLINE - - %-4d 5 LOAD_CONST 1 (1) - 8 RETURN_VALUE -"""%(_f.func_code.co_firstlineno + 1, - _f.func_code.co_firstlineno + 2) - - def bug708901(): for res in range(1, 10): @@ -131,10 +120,7 @@ self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT) def test_dis(self): - if check_impl_detail(pypy=True): - self.do_disassembly_test(_f, dis_f_pypy) - else: - self.do_disassembly_test(_f, dis_f_cpy) + self.do_disassembly_test(_f, dis_f) @impl_detail("PyPy compilers produce different opcodes") def test_bug_708901(self): From afa at codespeak.net Thu Feb 12 13:21:09 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 12 Feb 2009 13:21:09 +0100 (CET) Subject: [pypy-svn] r61775 - in pypy/trunk/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20090212122109.35ADF169E33@codespeak.net> Author: afa Date: Thu Feb 12 13:21:08 2009 New Revision: 61775 Modified: pypy/trunk/pypy/lib/_ctypes/pointer.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py Log: Functions expecting POINTER(A) should allow pointers to subclasses of A. test and fix. Modified: pypy/trunk/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/pointer.py (original) +++ pypy/trunk/pypy/lib/_ctypes/pointer.py Thu Feb 12 13:21:08 2009 @@ -38,7 +38,7 @@ if isinstance(value, self._type_): return byref(value) # Array instances are also pointers when the item types are the same. - if isinstance(value, Array): + if isinstance(value, (_Pointer, Array)): if issubclass(type(value)._type_, self._type_): return value return _CDataMeta.from_param(self, value) Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_parameters.py Thu Feb 12 13:21:08 2009 @@ -49,6 +49,18 @@ assert CWCHARP.from_param("abc") == "abcabcabc" + def test_pointer_subclasses(self): + from ctypes import * + + Void_pp = POINTER(c_void_p) + class My_void_p(c_void_p): + pass + + My_void_pp = POINTER(My_void_p) + o = My_void_pp() + + assert Void_pp.from_param(o) is o + # XXX Replace by c_char_p tests def test_cstrings(self): py.test.skip("testing implementation internals") From arigo at codespeak.net Thu Feb 12 13:28:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 13:28:56 +0100 (CET) Subject: [pypy-svn] r61776 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090212122856.7C13E169EBC@codespeak.net> Author: arigo Date: Thu Feb 12 13:28:53 2009 New Revision: 61776 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: A new (failing) test. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Feb 12 13:28:53 2009 @@ -66,6 +66,7 @@ # ____________________________________________________________ class A: + ofs_next = runner.CPU.offsetof(NODE, 'next') ofs_value = runner.CPU.offsetof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) # @@ -426,3 +427,38 @@ vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] assert guard_op.storage_info.setfields == [(0, G.ofs_value, 1)] + +# ____________________________________________________________ + +class H: + locals().update(A.__dict__) # :-) + # + containernode = lltype.malloc(NODE) + containernode.next = lltype.malloc(NODE) + containernode.next.value = 20 + n0 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, containernode)) + n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, containernode.next)) + nextnode = lltype.malloc(NODE) + nextnode.value = 19 + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) + v = BoxInt(containernode.next.value) + v2 = BoxInt(nextnode.value) + ops = [ + MergePoint('merge_point', [n0], []), + ResOperation('getfield_gc_ptr', [n0, ConstInt(ofs_next)], [n1]), + ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('new_with_vtable', [ConstInt(size_of_node), + ConstAddr(node_vtable, cpu)], [n2]), + ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc_ptr', [n0, ConstInt(ofs_next), n2], []), + Jump('jump', [n0], []), + ] + +def test_H_intersect_input_and_output(): + spec = PerfectSpecializer(H.ops) + spec.find_nodes() + spec.intersect_input_and_output() + assert spec.nodes[H.n0].escaped + assert spec.nodes[H.n1].escaped + assert spec.nodes[H.n2].escaped From fijal at codespeak.net Thu Feb 12 13:44:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 13:44:52 +0100 (CET) Subject: [pypy-svn] r61777 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090212124452.E35C4169EB2@codespeak.net> Author: fijal Date: Thu Feb 12 13:44:50 2009 New Revision: 61777 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: (arigo, fijal) Two tests, one pass one fail Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Feb 12 13:44:50 2009 @@ -462,3 +462,62 @@ assert spec.nodes[H.n0].escaped assert spec.nodes[H.n1].escaped assert spec.nodes[H.n2].escaped + +# ____________________________________________________________ + +class I: + locals().update(A.__dict__) # :-) + # + containernode = lltype.malloc(NODE) + containernode.next = lltype.malloc(NODE) + containernode.next.value = 20 + n0 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, containernode)) + nextnode = lltype.malloc(NODE) + nextnode.value = 19 + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) + ops = [ + MergePoint('merge_point', [n0], []), + ResOperation('new_with_vtable', [ConstInt(size_of_node), + ConstAddr(node_vtable, cpu)], [n2]), + ResOperation('setfield_gc_ptr', [n2, ConstInt(ofs_next), n0], []), + Jump('jump', [n2], []), + ] + +def test_I_intersect_input_and_output(): + spec = PerfectSpecializer(I.ops) + spec.find_nodes() + spec.intersect_input_and_output() + assert spec.nodes[I.n0].escaped + assert spec.nodes[I.n2].escaped + + +# ____________________________________________________________ + +class J: + locals().update(A.__dict__) # :-) + # + containernode = lltype.malloc(NODE) + containernode.next = lltype.malloc(NODE) + containernode.next.value = 20 + n0 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, containernode)) + nextnode = lltype.malloc(NODE) + nextnode.value = 19 + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) + n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) + ops = [ + MergePoint('merge_point', [n0], []), + ResOperation('getfield_gc_ptr', [n0, ConstInt(ofs_next)], [n1]), + ResOperation('new_with_vtable', [ConstInt(size_of_node), + ConstAddr(node_vtable, cpu)], [n2]), + ResOperation('setfield_gc_ptr', [n2, ConstInt(ofs_next), n1], []), + Jump('jump', [n2], []), + ] + +def test_J_intersect_input_and_output(): + spec = PerfectSpecializer(J.ops) + spec.find_nodes() + spec.intersect_input_and_output() + assert not spec.nodes[J.n0].escaped + assert spec.nodes[J.n1].escaped + assert not spec.nodes[J.n2].escaped + From fijal at codespeak.net Thu Feb 12 13:54:22 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 13:54:22 +0100 (CET) Subject: [pypy-svn] r61778 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090212125422.55BF6168434@codespeak.net> Author: fijal Date: Thu Feb 12 13:54:21 2009 New Revision: 61778 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: (arigo, fijal) A trivial fix for startboxes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 13:54:21 2009 @@ -238,7 +238,8 @@ fieldbox = op.args[1] assert isinstance(fieldbox, ConstInt) field = fieldbox.getint() - instnode.curfields[field] = self.getnode(op.args[2]) + fieldnode = self.getnode(op.args[2]) + instnode.curfields[field] = fieldnode continue elif opname.startswith('getfield_gc_'): instnode = self.getnode(op.args[0]) @@ -252,6 +253,8 @@ fieldnode = instnode.origfields[field] else: fieldnode = InstanceNode(box, escaped=False) + if instnode.startbox: + fieldnode.startbox = True instnode.origfields[field] = fieldnode self.nodes[box] = fieldnode continue From fijal at codespeak.net Thu Feb 12 14:19:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 14:19:52 +0100 (CET) Subject: [pypy-svn] r61779 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090212131952.6F494169E44@codespeak.net> Author: fijal Date: Thu Feb 12 14:19:51 2009 New Revision: 61779 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: (arigo, fijal) Fix the bug by reinventing a bit logic about escaping. We're too fried to make sure that we did the right thing and definitely too fried to think about efficiency :-) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 14:19:51 2009 @@ -121,7 +121,6 @@ self.startbox = startbox self.const = const self.virtual = False - self.star = False self.cls = None self.origfields = {} self.curfields = {} @@ -135,13 +134,11 @@ for node in self.curfields.values(): node.escape_if_startbox(memo) - def set_escaping_flag(self, other): - if not self.escaped: - for ofs, node in self.origfields.items(): - if ofs in other.curfields: - node.set_escaping_flag(other.curfields[ofs]) - else: - other.escaped = True + def add_to_dependency_graph(self, other, dep_graph): + dep_graph.append((self, other)) + for ofs, node in self.origfields.items(): + if ofs in other.curfields: + node.add_to_dependency_graph(other.curfields[ofs], dep_graph) def intersect(self, other): if not other.cls: @@ -175,6 +172,14 @@ for ofs, subspecnode in specnode.fields: self.curfields[ofs].adapt_to(subspecnode) + def __repr__(self): + flags = '' + if self.escaped: flags += 'e' + if self.startbox: flags += 's' + if self.const: flags += 'c' + if self.virtual: flags += 'v' + return "" % (self.source, flags) + def optimize_loop(metainterp, old_loops, operations): if not metainterp._specialize: # for tests only @@ -211,6 +216,7 @@ def __init__(self, operations): self.operations = operations self.nodes = {} + self.dependency_graph = [] def getnode(self, box): try: @@ -240,6 +246,8 @@ field = fieldbox.getint() fieldnode = self.getnode(op.args[2]) instnode.curfields[field] = fieldnode + if opname == 'setfield_gc_ptr': + self.dependency_graph.append((instnode, fieldnode)) continue elif opname.startswith('getfield_gc_'): instnode = self.getnode(op.args[0]) @@ -255,6 +263,7 @@ fieldnode = InstanceNode(box, escaped=False) if instnode.startbox: fieldnode.startbox = True + self.dependency_graph.append((instnode, fieldnode)) instnode.origfields[field] = fieldnode self.nodes[box] = fieldnode continue @@ -262,7 +271,6 @@ instnode = self.getnode(op.args[0]) if instnode.cls is None: instnode.cls = InstanceNode(op.args[1]) - instnode.cls.star = True continue elif opname not in ('oois', 'ooisnot', 'ooisnull', 'oononnull'): @@ -282,7 +290,17 @@ for i in range(len(end_args)): box = self.operations[0].args[i] other_box = end_args[i] - self.nodes[box].set_escaping_flag(self.nodes[other_box]) + self.nodes[box].add_to_dependency_graph(self.nodes[other_box], + self.dependency_graph) + # XXX find efficient algorithm, we're too fried for that by now + done = False + while not done: + done = True + for instnode, fieldnode in self.dependency_graph: + if instnode.escaped: + if not fieldnode.escaped: + fieldnode.escaped = True + done = False def intersect_input_and_output(self): # Step (3) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Feb 12 14:19:51 2009 @@ -99,7 +99,6 @@ assert spec.nodes[A.sum] is not spec.nodes[A.sum2] assert spec.nodes[A.n1] is not spec.nodes[A.n2] assert spec.nodes[A.n1].cls.source.value == node_vtable_adr - assert spec.nodes[A.n1].cls.star assert not spec.nodes[A.n1].escaped assert spec.nodes[A.n2].cls.source.value == node_vtable_adr assert not spec.nodes[A.n2].escaped From fijal at codespeak.net Thu Feb 12 14:22:46 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 14:22:46 +0100 (CET) Subject: [pypy-svn] r61780 - pypy/branch/pyjitpl5/pypy/rlib Message-ID: <20090212132246.5CAA1169E44@codespeak.net> Author: fijal Date: Thu Feb 12 14:22:45 2009 New Revision: 61780 Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py Log: (arigo, fijal) Wuaaa Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rlib/jit.py (original) +++ pypy/branch/pyjitpl5/pypy/rlib/jit.py Thu Feb 12 14:22:45 2009 @@ -84,12 +84,15 @@ } unroll_parameters = unrolling_iterable(PARAMETERS.keys()) -class JitDriver: +class JitDriver: """Base class to declare fine-grained user control on the JIT. So far, there must be a singleton instance of JitDriver. This style will allow us (later) to support a single RPython program with several independent JITting interpreters in it. """ + + virtualizables = [] + def __init__(self, greens=None, reds=None, virtualizables=None): if greens is not None: self.greens = greens From arigo at codespeak.net Thu Feb 12 14:38:46 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 14:38:46 +0100 (CET) Subject: [pypy-svn] r61781 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090212133846.91E89169EB4@codespeak.net> Author: arigo Date: Thu Feb 12 14:38:44 2009 New Revision: 61781 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: (fijal, arigo) In-progress: virtualizables in optimize.py. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 14:38:44 2009 @@ -121,6 +121,7 @@ self.startbox = startbox self.const = const self.virtual = False + self.virtualized = False self.cls = None self.origfields = {} self.curfields = {} @@ -272,6 +273,10 @@ if instnode.cls is None: instnode.cls = InstanceNode(op.args[1]) continue + elif opname.startswith('guard_nonvirtualized_'): + instnode = self.getnode(op.args[0]) + instnode.virtualized = True + continue elif opname not in ('oois', 'ooisnot', 'ooisnull', 'oononnull'): # default case @@ -297,7 +302,7 @@ while not done: done = True for instnode, fieldnode in self.dependency_graph: - if instnode.escaped: + if instnode.escaped and not instnode.virtualized: if not fieldnode.escaped: fieldnode.escaped = True done = False @@ -412,6 +417,13 @@ op = self.optimize_guard(op) newoperations.append(op) continue + elif opname.startswith('guard_nonvirtualized_'): + instnode = self.nodes[op.args[0]] + if instnode.virtualized: + continue + op = self.optimize_guard(op) + newoperations.append(op) + continue elif opname.startswith('guard_'): if opname == 'guard_true' or opname == 'guard_false': if self.nodes[op.args[0]].const: @@ -421,7 +433,7 @@ continue elif opname.startswith('getfield_gc_'): instnode = self.nodes[op.args[0]] - if instnode.virtual: + if instnode.virtual or instnode.virtualized: ofs = op.args[1].getint() assert ofs in instnode.curfields # xxx self.nodes[op.results[0]] = instnode.curfields[ofs] @@ -439,7 +451,7 @@ elif opname.startswith('setfield_gc_'): instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] - if instnode.virtual: + if instnode.virtual or instnode.virtualized: ofs = op.args[1].getint() instnode.curfields[ofs] = valuenode # XXX hack Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Thu Feb 12 14:38:44 2009 @@ -0,0 +1,115 @@ +from pypy.rpython.lltypesystem import lltype, rclass, llmemory +from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR +from pypy.rpython.lltypesystem.rvirtualizable2 import VirtualizableAccessor +from pypy.jit.backend.llgraph import runner +from pypy.jit.metainterp import heaptracker +from pypy.jit.metainterp.history import (ResOperation, MergePoint, Jump, + ConstInt, ConstAddr, BoxInt, BoxPtr) +from pypy.jit.metainterp.optimize import PerfectSpecializer +from pypy.jit.metainterp.virtualizable import VirtualizableDesc +from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable) + +# ____________________________________________________________ + +XY = lltype.GcStruct( + 'XY', + ('parent', rclass.OBJECT), + ('vable_base', llmemory.Address), + ('vable_rti', VABLERTIPTR), + ('x', lltype.Signed), + ('node', lltype.Ptr(NODE)), + hints = {'virtualizable2': True}, + adtmeths = {'access': VirtualizableAccessor()}) +XY._adtmeths['access'].initialize(XY, ['x', 'node']) + +xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) +xy_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 3, immortal=True) +xy_vtable.name[0] = 'X' +xy_vtable.name[1] = 'Y' +xy_vtable.name[2] = '\x00' +heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable) + +XYSUB = lltype.GcStruct( + 'XYSUB', + ('parent', XY), + ('z', lltype.Signed), + hints = {'virtualizable2': True}, + adtmeths = {'access': VirtualizableAccessor()}) +XYSUB._adtmeths['access'].initialize(XYSUB, ['z'], PARENT=XY) + +xysub_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) +xysub_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 6, + immortal=True) +xysub_vtable.name[0] = 'X' +xysub_vtable.name[1] = 'Y' +xysub_vtable.name[2] = 'S' +xysub_vtable.name[3] = 'U' +xysub_vtable.name[4] = 'B' +xysub_vtable.name[5] = '\x00' +heaptracker.set_testing_vtable_for_gcstruct(XYSUB, xysub_vtable) + +# ____________________________________________________________ + +xy_desc = VirtualizableDesc(cpu, XY) + +# ____________________________________________________________ + +class A: + ofs_node = runner.CPU.offsetof(XY, 'node') + ofs_value = runner.CPU.offsetof(NODE, 'value') + size_of_node = runner.CPU.sizeof(NODE) + # + frame = lltype.malloc(XY) + frame.vable_rti = lltype.nullptr(XY.vable_rti.TO) + frame.node = lltype.malloc(NODE) + frame.node.value = 20 + sum = BoxInt(0) + fr = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame)) + n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + nextnode = lltype.malloc(NODE) + nextnode.value = 19 + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) + v = BoxInt(frame.node.value) + v2 = BoxInt(nextnode.value) + sum2 = BoxInt(0 + frame.node.value) + ops = [ + MergePoint('merge_point', [sum, fr], []), + ResOperation('guard_nonvirtualized__4', [fr, ConstInt(ofs_node)], []), + ResOperation('getfield_gc_ptr', [fr, ConstInt(ofs_node)], [n1]), + ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('int_add', [sum, v], [sum2]), + ResOperation('new_with_vtable', [ConstInt(size_of_node), + ConstAddr(node_vtable, cpu)], [n2]), + ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc_ptr', [fr, ConstInt(ofs_node), n2], []), + Jump('jump', [sum2, fr], []), + ] + ops[1].desc = xy_desc + +def test_A_find_nodes(): + spec = PerfectSpecializer(A.ops) + spec.find_nodes() + assert spec.nodes[A.fr].virtualized + +def test_A_intersect_input_and_output(): + spec = PerfectSpecializer(A.ops) + spec.find_nodes() + spec.intersect_input_and_output() + assert spec.nodes[A.fr].escaped + assert spec.nodes[A.fr].virtualized + assert not spec.nodes[A.n1].escaped + assert not spec.nodes[A.n2].escaped + +def test_A_optimize_loop(): + operations = A.ops[:] + spec = PerfectSpecializer(operations) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + assert equaloplists(operations, [ + MergePoint('merge_point', [A.sum, A.n1, A.v], []), + ResOperation('int_sub', [A.v, ConstInt(1)], [A.v2]), + ResOperation('int_add', [A.sum, A.v], [A.sum2]), + Jump('jump', [A.sum2, A.n1, A.v2], []), + ]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Thu Feb 12 14:38:44 2009 @@ -1,57 +1,14 @@ import py -from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory from pypy.rpython.annlowlevel import llhelper from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.jit.metainterp import heaptracker from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR -from pypy.rpython.lltypesystem.rvirtualizable2 import VirtualizableAccessor promote_virtualizable = lloperation.llop.promote_virtualizable debug_print = lloperation.llop.debug_print - -# ____________________________________________________________ - -XY = lltype.GcStruct( - 'XY', - ('parent', rclass.OBJECT), - ('vable_base', llmemory.Address), - ('vable_rti', VABLERTIPTR), - ('x', lltype.Signed), - ('y', lltype.Signed), - hints = {'virtualizable2': True}, - adtmeths = {'access': VirtualizableAccessor()}) -XY._adtmeths['access'].initialize(XY, ['x', 'y']) - -xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) -xy_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 3, immortal=True) -xy_vtable.name[0] = 'X' -xy_vtable.name[1] = 'Y' -xy_vtable.name[2] = '\x00' -heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable) - -XYSUB = lltype.GcStruct( - 'XYSUB', - ('parent', XY), - ('z', lltype.Signed), - hints = {'virtualizable2': True}, - adtmeths = {'access': VirtualizableAccessor()}) -XYSUB._adtmeths['access'].initialize(XYSUB, ['z'], PARENT=XY) - -xysub_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) -xysub_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 6, - immortal=True) -xysub_vtable.name[0] = 'X' -xysub_vtable.name[1] = 'Y' -xysub_vtable.name[2] = 'S' -xysub_vtable.name[3] = 'U' -xysub_vtable.name[4] = 'B' -xysub_vtable.name[5] = '\x00' -heaptracker.set_testing_vtable_for_gcstruct(XYSUB, xysub_vtable) - # ____________________________________________________________ class ExplicitVirtualizableTests: From antocuni at codespeak.net Thu Feb 12 14:53:55 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 12 Feb 2009 14:53:55 +0100 (CET) Subject: [pypy-svn] r61782 - pypy/branch/oo-jit/pypy/jit/codegen/cli Message-ID: <20090212135355.33CEC169E33@codespeak.net> Author: antocuni Date: Thu Feb 12 14:53:53 2009 New Revision: 61782 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Log: automatically generate *_ovf and *_zer operations Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Thu Feb 12 14:53:53 2009 @@ -347,12 +347,13 @@ def getExceptionType(self): raise NotImplementedError + def emit_op(self): + raise NotImplementedError + def emit(self): il = self.meth.il lbl = il.BeginExceptionBlock() - self.pushAllArgs() - il.Emit(self.getOpCode()) - self.storeResult() + self.emit_op() il.Emit(OpCodes.Leave, lbl) il.BeginCatchBlock(self.getExceptionType()) il.Emit(OpCodes.Ldc_I4, 1) @@ -360,6 +361,7 @@ il.EndExceptionBlock() + class RaisingBinaryOp(CatchAndRaiseMixin, BinaryOp): pass @@ -405,12 +407,11 @@ out = {} for opname, value in ops.iteritems(): renderOp(baseclass, opname, value, out) - return out -def renderOp(baseclass, opname, value, out, optional_lines=''): +def renderOp(baseclass, opname, value, out): if isinstance(value, str): - renderSimpleOp(baseclass, opname, value, out, optional_lines) + renderSimpleOp(baseclass, opname, value, out) elif value is cli_opcodes.DoNothing: # create a new subclass of SameAs; we can't use SameAs directly # because its restype could be patched later @@ -419,9 +420,9 @@ assert isinstance(value, list) steps = value if len(steps) == 1 and isinstance(steps[0], cli_opcodes.MapException): - #renderRaisingOp(baseclass, opname, steps[0], out) - return # XXX - renderCustomOp(baseclass, opname, value, out) + renderRaisingOp(baseclass, opname, steps[0], out) + else: + renderCustomOp(baseclass, opname, value, out) # fix the restype for comparison ops and casts if is_comparison(opname): @@ -431,41 +432,19 @@ funcname = 'restype_%s' % to out[opname].restype = globals()[funcname] -def renderSimpleOp(baseclass, opname, value, out, optional_lines=''): + +def renderSimpleOp(baseclass, opname, value, out): attrname = opcode2attrname(value) source = py.code.Source(""" class %(opname)s (%(baseclass)s): def getOpCode(self): return OpCodes.%(attrname)s - -%(optional_lines)s """ % locals()) code = source.compile() exec code in globals(), out -## def get_exctype(exctype_str): -## if exctype_str == '[mscorlib]System.OverflowException': -## return typeof(System.OverflowException) -## elif exctype_str == '[mscorlib]System.DivideByZeroException': -## return typeof(System.DivideByZeroException) -## else: -## assert False, 'Unknown exception type' - -## def renderRaisingOp(baseclass, opname, value, out): -## mapping = value.mapping -## assert len(mapping) == 1, 'Catching more than one exception is not supported' -## exctype = mapping[0][0] -## assert exctype.startswith('[mscorlib]') -## exctype = exctype[len('[mscorlib]'):] -## source = """ -## def getExceptionType(self): -## return typeof(%(exctype)s) -## """ % locals() -## baseclass = 'Raising' + baseclass -## renderOp(baseclass, opname, value.instr, out, source) - -def renderCustomOp(baseclass, opname, steps, out): +def renderCustomOp(baseclass, opname, steps, out, emitName='emit', optional_lines=''): assert steps body = [] for step in steps: @@ -479,7 +458,9 @@ attrname = opcode2attrname(step) body.append('self.meth.il.Emit(OpCodes.%s)' % attrname) elif isinstance(step, cli_opcodes.MapException): - return # XXX, TODO + # MapException is supported only if it's the only element of the + # instr list, look inside RenderOp + assert False, 'MapException not supported here' else: return # ignore it for now @@ -487,12 +468,39 @@ body.append('self.storeResult()') emit = py.code.Source('\n'.join(body)) - emit = emit.putaround('def emit(self):') - source = emit.putaround('class %(opname)s (%(baseclass)s):' % locals()) + emit = emit.putaround('def %s(self):' % emitName).indent(' '*8) + source = py.code.Source(""" + class %(opname)s (%(baseclass)s): +%(emit)s +%(optional_lines)s + """ % locals()) + code = source.compile() exec code in globals(), out +def renderRaisingOp(baseclass, opname, value, out): + mapping = value.mapping + assert len(mapping) == 1, 'Catching more than one exception is not supported' + exctype = mapping[0][0] + assert exctype.startswith('[mscorlib]') + exctype = exctype[len('[mscorlib]'):] + source = """ + def getExceptionType(self): + return typeof(%(exctype)s) + """ % locals() + baseclass = 'Raising' + baseclass + renderCustomOp(baseclass, opname, value.instr, out, 'emit_op', source) + +def get_exctype(exctype_str): + if exctype_str == '[mscorlib]System.OverflowException': + return typeof(System.OverflowException) + elif exctype_str == '[mscorlib]System.DivideByZeroException': + return typeof(System.DivideByZeroException) + else: + assert False, 'Unknown exception type' + + UNARYOPS = fillops(cli_opcodes.unary_ops, "UnaryOp") BINARYOPS = fillops(cli_opcodes.binary_ops, "BinaryOp") Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Thu Feb 12 14:53:53 2009 @@ -818,15 +818,12 @@ @specialize.arg(1) def genraisingop2(self, opname, gv_arg1, gv_arg2): - if opname == 'int_add_ovf': - opcls = ops.IntAddOvf - op = opcls(self.meth, gv_arg1, gv_arg2) - self.appendop(op) - gv_res = op.gv_res() - gv_excflag = op.gv_excflag() - return gv_res, gv_excflag - else: - assert False + opcls = ops.getopclass2(opname) + op = opcls(self.meth, gv_arg1, gv_arg2) + self.appendop(op) + gv_res = op.gv_res() + gv_excflag = op.gv_excflag() + return gv_res, gv_excflag def genop_call(self, sigtoken, gv_fnptr, args_gv): op = ops.Call(self.meth, sigtoken, gv_fnptr, args_gv) From antocuni at codespeak.net Thu Feb 12 15:13:09 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 12 Feb 2009 15:13:09 +0100 (CET) Subject: [pypy-svn] r61783 - pypy/branch/oo-jit/pypy/jit/codegen/cli/test Message-ID: <20090212141309.92D15169EA8@codespeak.net> Author: antocuni Date: Thu Feb 12 15:13:08 2009 New Revision: 61783 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Log: add support for unary raisinops Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Thu Feb 12 15:13:08 2009 @@ -70,10 +70,16 @@ py.test.skip('mono 2.2 crashes') def test_ovfcheck1_direct(self): - py.test.skip('fixme') + import sys + # XXX: this test is partly copied from rgenop_tests, because + # int_abs_ovf is not yet supported. Delete this method as soon as it + # is + yield self.ovfcheck1_direct, "int_neg_ovf", [(18, -18), + (-18, 18), + (sys.maxint, -sys.maxint), + (-sys.maxint, sys.maxint), + (-sys.maxint-1, None)] - def test_ovfcheck2_direct(self): - py.test.skip('fixme') def test_cast_direct(self): py.test.skip('fixme') @@ -136,6 +142,3 @@ def test_genconst_from_frame_float_var_compile(self): py.test.skip('fixme: add support for frames') - - def test_ovfcheck1_compile(self): - py.test.skip('fixme') From fijal at codespeak.net Thu Feb 12 15:18:37 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 15:18:37 +0100 (CET) Subject: [pypy-svn] r61784 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090212141837.3BC0D169EAD@codespeak.net> Author: fijal Date: Thu Feb 12 15:18:36 2009 New Revision: 61784 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: (arigo, fijal) Remove setfield_gc_* and friends, now we encode the type of set/get field in an offset, which became fielddesc, maintained by CPU Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Feb 12 15:18:36 2009 @@ -64,14 +64,10 @@ 'ooisnull' : (('ptr',), 'bool'), 'oois' : (('ptr', 'ptr'), 'bool'), 'ooisnot' : (('ptr', 'ptr'), 'bool'), - 'setfield_gc__4' : (('ptr', 'fieldname', 'int'), None), - 'getfield_gc__4' : (('ptr', 'fieldname'), 'int'), - 'setfield_raw__4' : (('ptr', 'fieldname', 'int'), None), - 'getfield_raw__4' : (('ptr', 'fieldname'), 'int'), - 'setfield_gc_ptr' : (('ptr', 'fieldname', 'ptr'), None), - 'getfield_gc_ptr' : (('ptr', 'fieldname'), 'ptr'), - 'setfield_raw_ptr': (('ptr', 'fieldname', 'ptr'), None), - 'getfield_raw_ptr': (('ptr', 'fieldname'), 'ptr'), + 'setfield_gc' : (('ptr', 'fieldname', 'intorptr'), None), + 'getfield_gc' : (('ptr', 'fieldname'), 'intorptr'), + 'setfield_raw' : (('ptr', 'fieldname', 'intorptr'), None), + 'getfield_raw' : (('ptr', 'fieldname'), 'intotptr'), 'call_ptr' : (('ptr', 'varargs'), 'ptr'), 'call__4' : (('ptr', 'varargs'), 'int'), 'call_void' : (('ptr', 'varargs'), None), @@ -139,13 +135,22 @@ types = types[:-1] + ('int',) * (len(lst) - len(types) + 1) assert len(types) == len(lst) for elem, tp in zip(lst, types): + if len(lst) >= 2: + extraarg = lst[1] + else: + extraarg = None if isinstance(elem, Constant): - res_l.append('(%s)' % repr1(elem, tp, cpu)) + res_l.append('(%s)' % repr1(elem, tp, cpu, extraarg)) else: - res_l.append(repr1(elem, tp, cpu)) + res_l.append(repr1(elem, tp, cpu, extraarg)) return '[%s]' % (', '.join(res_l)) -def repr1(x, tp, cpu): +def repr1(x, tp, cpu, extraarg): + if tp == "intorptr": + if extraarg % 2: + tp = "ptr" + else: + tp = "int" if tp == 'int': return str(x) elif tp == 'ptr': @@ -171,7 +176,7 @@ assert x == 0 or x == 1 return str(bool(x)) elif tp == 'fieldname': - return str(symbolic.TokenToField[x][1]) + return str(symbolic.TokenToField[x/2][1]) else: raise NotImplementedError("tp = %s" % tp) @@ -376,7 +381,11 @@ if res is None: resdata = '' else: - resdata = '-> ' + repr1(res, restype, self.cpu) + if len(values) >= 2: + extraarg = values[1] + else: + extraarg = None + resdata = '-> ' + repr1(res, restype, self.cpu, extraarg) # fish the types log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, self.cpu), resdata)) @@ -630,76 +639,42 @@ TYPE = symbolic.Size2Type[typesize] ptr = lltype.malloc(TYPE) ptr = lltype.cast_opaque_ptr(llmemory.GCREF, ptr) - self.op_setfield_gc__4(ptr, 1, vtable) + self.op_setfield_gc(ptr, 2, vtable) return ptr - def op_getfield_gc__4(self, ptr, offset): - STRUCT, fieldname = symbolic.TokenToField[offset] + def op_getfield_gc(self, ptr, fielddesc): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) return getattr(ptr, fieldname) - def op_getfield_raw__4(self, intval, offset): - STRUCT, fieldname = symbolic.TokenToField[offset] - ptr = llmemory.cast_adr_to_ptr(self.cpu.cast_int_to_adr(intval), - lltype.Ptr(STRUCT)) - return getattr(ptr, fieldname) - - def op_getfield_raw_ptr(self, intval, offset): - STRUCT, fieldname = symbolic.TokenToField[offset] + def op_getfield_raw(self, intval, fielddesc): + STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] ptr = llmemory.cast_adr_to_ptr(self.cpu.cast_int_to_adr(intval), lltype.Ptr(STRUCT)) return getattr(ptr, fieldname) - def op_getfield_gc_ptr(self, ptr, offset): - STRUCT, fieldname = symbolic.TokenToField[offset] - ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) - return getattr(ptr, fieldname) - - def op_setfield_gc__4(self, ptr, offset, newintvalue): - STRUCT, fieldname = symbolic.TokenToField[offset] - ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) - FIELDTYPE = getattr(STRUCT, fieldname) - if isinstance(FIELDTYPE, lltype.Ptr): - assert FIELDTYPE.TO._gckind == 'raw' - newvalue = llmemory.cast_adr_to_ptr( - self.cpu.cast_int_to_adr(newintvalue), - FIELDTYPE) - elif FIELDTYPE == llmemory.Address: - newvalue = self.cpu.cast_int_to_adr(newintvalue) - else: - newvalue = newintvalue - setattr(ptr, fieldname, newvalue) - - def op_setfield_raw__4(self, intval, offset, newintvalue): + def op_setfield_gc(self, ptr, fielddesc, newvalue): + offset = fielddesc/2 STRUCT, fieldname = symbolic.TokenToField[offset] - ptr = llmemory.cast_adr_to_ptr(self.cpu.cast_int_to_adr(intval), - lltype.Ptr(STRUCT)) + if lltype.typeOf(ptr) == llmemory.GCREF: + ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) FIELDTYPE = getattr(STRUCT, fieldname) - if isinstance(FIELDTYPE, lltype.Ptr): - assert FIELDTYPE.TO._gckind == 'raw' - newvalue = llmemory.cast_adr_to_ptr( - self.cpu.cast_int_to_adr(newintvalue), - FIELDTYPE) - elif FIELDTYPE == llmemory.Address: - newvalue = self.cpu.cast_int_to_adr(newintvalue) + if fielddesc % 2: + newvalue = lltype.cast_opaque_ptr(FIELDTYPE, newvalue) else: - newvalue = newintvalue + if isinstance(FIELDTYPE, lltype.Ptr): + assert FIELDTYPE.TO._gckind == 'raw' + newvalue = llmemory.cast_adr_to_ptr( + self.cpu.cast_int_to_adr(newvalue), + FIELDTYPE) + elif FIELDTYPE == llmemory.Address: + newvalue = self.cpu.cast_int_to_adr(newvalue) setattr(ptr, fieldname, newvalue) - def op_setfield_gc_ptr(self, ptr, offset, newvalue): - STRUCT, fieldname = symbolic.TokenToField[offset] - ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) - FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = lltype.cast_opaque_ptr(FIELDTYPE, newvalue) - setattr(ptr, fieldname, newvalue) - - def op_setfield_raw_ptr(self, intval, offset, newvalue): - STRUCT, fieldname = symbolic.TokenToField[offset] + def op_setfield_raw(self, intval, fielddesc, newvalue): ptr = llmemory.cast_adr_to_ptr(self.cpu.cast_int_to_adr(intval), lltype.Ptr(STRUCT)) - FIELDTYPE = getattr(STRUCT, fieldname) - newvalue = lltype.cast_opaque_ptr(FIELDTYPE, newvalue) - setattr(ptr, fieldname, newvalue) + self.op_setfield_gc(ptr, fielddesc, newvalue) def op_ooisnull(self, ptr): if lltype.typeOf(ptr) != llmemory.GCREF: Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Feb 12 15:18:36 2009 @@ -244,9 +244,20 @@ addresssuffix = '4' @staticmethod - def offsetof(S, fieldname): + def fielddescrof(S, fieldname): ofs, size = symbolic.get_field_token(S, fieldname) - return ofs + token = history.getkind(getattr(S, fieldname)) + if token == 'ptr': + bit = 1 + else: + bit = 0 + return ofs*2 + bit + + @staticmethod + def typefor(fielddesc): + if fielddesc % 2: + return 'ptr' + return 'int' @staticmethod def itemoffsetof(A): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Feb 12 15:18:36 2009 @@ -444,9 +444,10 @@ if RESULT is lltype.Void: return argname = v_inst.concretetype.TO._gckind - self.emit('%s_%s_%s' % (opname, argname, getkind_num(self.cpu, RESULT))) + self.emit('%s_%s' % (opname, argname)) self.emit(self.var_position(v_inst)) - offset = self.cpu.offsetof(v_inst.concretetype.TO, c_fieldname.value) + offset = self.cpu.fielddescrof(v_inst.concretetype.TO, + c_fieldname.value) self.emit(offset) self.register_var(op.result) @@ -460,9 +461,10 @@ if RESULT is lltype.Void: return argname = v_inst.concretetype.TO._gckind - self.emit('setfield_%s_%s' % (argname, getkind_num(self.cpu, RESULT))) + self.emit('setfield_%s' % (argname,)) self.emit(self.var_position(v_inst)) - offset = self.cpu.offsetof(v_inst.concretetype.TO, c_fieldname.value) + offset = self.cpu.fielddescrof(v_inst.concretetype.TO, + c_fieldname.value) self.emit(offset) self.emit(self.var_position(v_value)) @@ -629,9 +631,8 @@ metainterp._virtualizabledescs[TOPSTRUCT] = virtualizabledesc metainterp._can_have_virtualizables = virtualizabledesc # ^^^ stays None if this code is never seen - guard_field = self.cpu.offsetof(STRUCTTYPE, argname) - self.emit('guard_nonvirtualized_%s' % getkind_num(self.cpu, - FIELDTYPE)) + guard_field = self.cpu.fielddescrof(STRUCTTYPE, argname) + self.emit('guard_nonvirtualized') self.emit(self.var_position(op.args[0])) self.emit(self.get_position(virtualizabledesc)) self.emit(guard_field) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 15:18:36 2009 @@ -94,7 +94,6 @@ class TypeCache(object): pass type_cache = TypeCache() # XXX remove me later -type_cache.field_type = {} type_cache.class_size = {} def extract_runtime_data(cpu, specnode, valuebox, resultlist): @@ -103,14 +102,10 @@ return for ofs, subspecnode in specnode.fields: cls = specnode.known_class.getint() - typemarker = type_cache.field_type[cls, ofs] - if typemarker.startswith('_'): - simpletypemarker = 'int' - else: - simpletypemarker = typemarker - fieldbox = cpu.execute_operation('getfield_gc_' + typemarker, + tp = cpu.typefor(ofs) + fieldbox = cpu.execute_operation('getfield_gc', [valuebox, ConstInt(ofs)], - simpletypemarker) + tp) extract_runtime_data(cpu, subspecnode, fieldbox, resultlist) @@ -240,17 +235,16 @@ instnode.cls = InstanceNode(op.args[1]) self.nodes[box] = instnode continue - elif opname.startswith('setfield_gc_'): + elif opname == 'setfield_gc': instnode = self.getnode(op.args[0]) fieldbox = op.args[1] assert isinstance(fieldbox, ConstInt) field = fieldbox.getint() fieldnode = self.getnode(op.args[2]) instnode.curfields[field] = fieldnode - if opname == 'setfield_gc_ptr': - self.dependency_graph.append((instnode, fieldnode)) + self.dependency_graph.append((instnode, fieldnode)) continue - elif opname.startswith('getfield_gc_'): + elif opname == 'getfield_gc': instnode = self.getnode(op.args[0]) fieldbox = op.args[1] assert isinstance(fieldbox, ConstInt) @@ -431,7 +425,7 @@ op = self.optimize_guard(op) newoperations.append(op) continue - elif opname.startswith('getfield_gc_'): + elif opname == 'getfield_gc': instnode = self.nodes[op.args[0]] if instnode.virtual or instnode.virtualized: ofs = op.args[1].getint() @@ -448,18 +442,12 @@ key = instnode.cls.source.getint() type_cache.class_size[key] = size continue - elif opname.startswith('setfield_gc_'): + elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] if instnode.virtual or instnode.virtualized: ofs = op.args[1].getint() instnode.curfields[ofs] = valuenode - # XXX hack - assert instnode.cls is not None - cls = instnode.cls.source.getint() - typemarker = opname[len('setfield_gc_'):] - type_cache.field_type[cls, ofs] = typemarker - # XXX end of hack continue assert not valuenode.virtual elif opname == 'ooisnull' or opname == 'oononnull': @@ -549,9 +537,9 @@ else: fieldbox = boxes_from_frame[index_in_arglist] vtable = storage.allocations[index_in_alloc] - opname = 'setfield_gc_' + type_cache.field_type[vtable, ofs] box = allocated_boxes[index_in_alloc] - history.execute_and_record(opname, [box, ConstInt(ofs), fieldbox], + history.execute_and_record('setfield_gc', + [box, ConstInt(ofs), fieldbox], 'void', False) newboxes = [] for index in storage.indices: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 12 15:18:36 2009 @@ -304,74 +304,30 @@ def opimpl_ptr_ne(self, box1, box2): self.execute('ooisnot', [box1, box2], 'int', True) - @arguments("box", "int") - def opimpl_getfield__1(self, box, offset): - self.execute('getfield__1', [box, ConstInt(offset)], 'int') - @arguments("box", "int") - def opimpl_getfield_pure__1(self, box, offset): - self.execute('getfield__1', [box, ConstInt(offset)], 'int', True) - @arguments("box", "int", "box") - def opimpl_setfield__1(self, box, offset, valuebox): - self.execute('setfield__1', [box, ConstInt(offset), valuebox], 'void') - - @arguments("box", "int") - def opimpl_getfield__2(self, box, offset): - self.execute('getfield__2', [box, ConstInt(offset)], 'int') - @arguments("box", "int") - def opimpl_getfield_pure__2(self, box, offset): - self.execute('getfield__2', [box, ConstInt(offset)], 'int', True) - @arguments("box", "int", "box") - def opimpl_setfield__2(self, box, offset, valuebox): - self.execute('setfield__2', [box, ConstInt(offset), valuebox], 'void') @arguments("box", "int") - def opimpl_getfield_gc__4(self, box, offset): - self.execute('getfield_gc__4', [box, ConstInt(offset)], 'int') - @arguments("box", "int") - def opimpl_getfield_pure_gc__4(self, box, offset): - self.execute('getfield_gc__4', [box, ConstInt(offset)], 'int', True) + def opimpl_getfield_gc(self, box, fielddesc): + tp = self.metainterp.cpu.typefor(fielddesc) + self.execute('getfield_gc', [box, ConstInt(fielddesc)], tp) + @arguments("box", "int") + def opimpl_getfield_pure_gc(self, box, fielddesc): + tp = self.metainterp.cpu.typefor(fielddesc) + self.execute('getfield_gc', [box, ConstInt(fielddesc)], tp, True) @arguments("box", "int", "box") - def opimpl_setfield_gc__4(self, box, offset, valuebox): - self.execute('setfield_gc__4', [box, ConstInt(offset), valuebox], 'void') + def opimpl_setfield_gc(self, box, offset, valuebox): + self.execute('setfield_gc', [box, ConstInt(offset), valuebox], 'void') @arguments("box", "int") - def opimpl_getfield_raw__4(self, box, offset): - self.execute('getfield_raw__4', [box, ConstInt(offset)], 'int') - @arguments("box", "int") - def opimpl_getfield_pure_raw__4(self, box, offset): - self.execute('getfield_raw__4', [box, ConstInt(offset)], 'int', True) - @arguments("box", "int", "box") - def opimpl_setfield_raw__4(self, box, offset, valuebox): - self.execute('setfield_raw__4', [box, ConstInt(offset), valuebox], 'void') - - @arguments("box", "int") - def opimpl_getfield__8(self, box, offset): - self.execute('getfield__8', [box, ConstInt(offset)], 'int') - @arguments("box", "int") - def opimpl_getfield_pure__8(self, box, offset): - self.execute('getfield__8', [box, ConstInt(offset)], 'int', True) - @arguments("box", "int", "box") - def opimpl_setfield__8(self, box, offset, valuebox): - self.execute('setfield__8', [box, ConstInt(offset), valuebox], 'void') - - @arguments("box", "int") - def opimpl_getfield_gc_ptr(self, box, offset): - self.execute('getfield_gc_ptr', [box, ConstInt(offset)], 'ptr') - @arguments("box", "int") - def opimpl_getfield_pure_gc_ptr(self, box, offset): - self.execute('getfield_gc_ptr', [box, ConstInt(offset)], 'ptr', True) - @arguments("box", "int", "box") - def opimpl_setfield_gc_ptr(self, box, offset, valuebox): - self.execute('setfield_gc_ptr', [box, ConstInt(offset), valuebox], 'void') - @arguments("box", "int") - def opimpl_getfield_raw_ptr(self, box, offset): - self.execute('getfield_raw_ptr', [box, ConstInt(offset)], 'ptr') + def opimpl_getfield_raw(self, box, fielddesc): + tp = self.metainterp.cpu.typefor(fielddesc) + self.execute('getfield_raw', [box, ConstInt(fielddesc)], tp) @arguments("box", "int") - def opimpl_getfield_pure_raw_ptr(self, box, offset): - self.execute('getfield_raw_ptr', [box, ConstInt(offset)], 'ptr', True) + def opimpl_getfield_pure_raw(self, box, fielddesc): + tp = self.metainterp.cpu.typefor(fielddesc) + self.execute('getfield_raw', [box, ConstInt(offset)], tp, True) @arguments("box", "int", "box") - def opimpl_setfield_raw_ptr(self, box, offset, valuebox): - self.execute('setfield_raw_ptr', [box, ConstInt(offset), valuebox], 'void') + def opimpl_setfield_raw(self, box, offset, valuebox): + self.execute('setfield_raw', [box, ConstInt(offset), valuebox], 'void') @arguments("bytecode", "varargs") def opimpl_call(self, callee, varargs): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Feb 12 15:18:36 2009 @@ -66,8 +66,8 @@ # ____________________________________________________________ class A: - ofs_next = runner.CPU.offsetof(NODE, 'next') - ofs_value = runner.CPU.offsetof(NODE, 'value') + ofs_next = runner.CPU.fielddescrof(NODE, 'next') + ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) # startnode = lltype.malloc(NODE) @@ -84,12 +84,12 @@ ops = [ MergePoint('merge_point', [sum, n1], []), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), Jump('jump', [sum2, n2], []), ] @@ -134,12 +134,12 @@ ops = [ MergePoint('merge_point', [sum, n1], []), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), ResOperation('some_escaping_operation', [n2], []), # <== escaping Jump('jump', [sum2, n2], []), ] @@ -171,12 +171,12 @@ assert equaloplists(operations, [ MergePoint('merge_point', [B.sum, B.n1], []), # guard_class is gone - ResOperation('getfield_gc__4', [B.n1, ConstInt(B.ofs_value)], [B.v]), + ResOperation('getfield_gc', [B.n1, ConstInt(B.ofs_value)], [B.v]), ResOperation('int_sub', [B.v, ConstInt(1)], [B.v2]), ResOperation('int_add', [B.sum, B.v], [B.sum2]), ResOperation('new_with_vtable', [ConstInt(B.size_of_node), ConstAddr(node_vtable, cpu)], [B.n2]), - ResOperation('setfield_gc__4', [B.n2, ConstInt(B.ofs_value), B.v2], + ResOperation('setfield_gc', [B.n2, ConstInt(B.ofs_value), B.v2], []), ResOperation('some_escaping_operation', [B.n2], []), # <== escaping Jump('jump', [B.sum2, B.n2], []), @@ -189,13 +189,13 @@ ops = [ MergePoint('merge_point', [sum, n1], []), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), ResOperation('some_escaping_operation', [n1], []), # <== escaping ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), Jump('jump', [sum2, n2], []), ] @@ -226,13 +226,13 @@ assert equaloplists(operations, [ MergePoint('merge_point', [C.sum, C.n1], []), # guard_class is gone - ResOperation('getfield_gc__4', [C.n1, ConstInt(C.ofs_value)], [C.v]), + ResOperation('getfield_gc', [C.n1, ConstInt(C.ofs_value)], [C.v]), ResOperation('int_sub', [C.v, ConstInt(1)], [C.v2]), ResOperation('int_add', [C.sum, C.v], [C.sum2]), ResOperation('some_escaping_operation', [C.n1], []), # <== escaping ResOperation('new_with_vtable', [ConstInt(C.size_of_node), ConstAddr(node_vtable, cpu)], [C.n2]), - ResOperation('setfield_gc__4', [C.n2, ConstInt(C.ofs_value), C.v2], + ResOperation('setfield_gc', [C.n2, ConstInt(C.ofs_value), C.v2], []), Jump('jump', [C.sum2, C.n2], []), ]) @@ -245,12 +245,12 @@ MergePoint('merge_point', [sum, n1], []), ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu)], []), # the only difference is different vtable ^^^^^^^^^^^^ - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), Jump('jump', [sum2, n2], []), ] @@ -266,12 +266,12 @@ ops = [ MergePoint('merge_point', [sum, n1], []), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), ResOperation('guard_true', [v2], []), Jump('jump', [sum2, n2], []), ] @@ -324,7 +324,7 @@ vt = cpu.cast_adr_to_int(node_vtable_adr) assert fake_history.ops == [ ('new_with_vtable', [ConstInt(type_cache.class_size[vt]), ConstInt(vt)]), - ('setfield_gc__4', ['allocated', ConstInt(E.ofs_value), v_v_b]) + ('setfield_gc', ['allocated', ConstInt(E.ofs_value), v_v_b]) ] assert newboxes == [v_sum_b, 'allocated'] @@ -341,12 +341,12 @@ ops = [ MergePoint('merge_point', [sum, n1, n3], []), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), ResOperation('ooisnot', [n2, n3], [vbool1]), GuardOp('guard_true', [vbool1], []), ResOperation('ooisnull', [n2], [vbool2]), @@ -391,16 +391,16 @@ ops = [ MergePoint('merge_point', [sum, n1], []), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), ConstInt(123)], []), - ResOperation('getfield_gc__4', [n2, ConstInt(ofs_value)], [v3]), + ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], [v3]), ResOperation('int_add', [v3, ConstInt(1)], [v4]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v4], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v4], []), ResOperation('guard_true', [v2], []), Jump('jump', [sum2, n2], []), ] @@ -444,13 +444,13 @@ v2 = BoxInt(nextnode.value) ops = [ MergePoint('merge_point', [n0], []), - ResOperation('getfield_gc_ptr', [n0, ConstInt(ofs_next)], [n1]), - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield_gc', [n0, ConstInt(ofs_next)], [n1]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), - ResOperation('setfield_gc_ptr', [n0, ConstInt(ofs_next), n2], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc', [n0, ConstInt(ofs_next), n2], []), Jump('jump', [n0], []), ] @@ -478,7 +478,7 @@ MergePoint('merge_point', [n0], []), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc_ptr', [n2, ConstInt(ofs_next), n0], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_next), n0], []), Jump('jump', [n2], []), ] @@ -505,10 +505,10 @@ n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, nextnode)) ops = [ MergePoint('merge_point', [n0], []), - ResOperation('getfield_gc_ptr', [n0, ConstInt(ofs_next)], [n1]), + ResOperation('getfield_gc', [n0, ConstInt(ofs_next)], [n1]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc_ptr', [n2, ConstInt(ofs_next), n1], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_next), n1], []), Jump('jump', [n2], []), ] From arigo at codespeak.net Thu Feb 12 15:21:21 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 15:21:21 +0100 (CET) Subject: [pypy-svn] r61785 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090212142121.B58A4169EAE@codespeak.net> Author: arigo Date: Thu Feb 12 15:21:21 2009 New Revision: 61785 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: (fijal, arigo) Fix the remaining tests, and fix some typos. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Feb 12 15:21:21 2009 @@ -67,7 +67,7 @@ 'setfield_gc' : (('ptr', 'fieldname', 'intorptr'), None), 'getfield_gc' : (('ptr', 'fieldname'), 'intorptr'), 'setfield_raw' : (('ptr', 'fieldname', 'intorptr'), None), - 'getfield_raw' : (('ptr', 'fieldname'), 'intotptr'), + 'getfield_raw' : (('ptr', 'fieldname'), 'intorptr'), 'call_ptr' : (('ptr', 'varargs'), 'ptr'), 'call__4' : (('ptr', 'varargs'), 'int'), 'call_void' : (('ptr', 'varargs'), None), Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 12 15:21:21 2009 @@ -314,8 +314,9 @@ tp = self.metainterp.cpu.typefor(fielddesc) self.execute('getfield_gc', [box, ConstInt(fielddesc)], tp, True) @arguments("box", "int", "box") - def opimpl_setfield_gc(self, box, offset, valuebox): - self.execute('setfield_gc', [box, ConstInt(offset), valuebox], 'void') + def opimpl_setfield_gc(self, box, fielddesc, valuebox): + self.execute('setfield_gc', [box, ConstInt(fielddesc), valuebox], + 'void') @arguments("box", "int") def opimpl_getfield_raw(self, box, fielddesc): @@ -324,10 +325,11 @@ @arguments("box", "int") def opimpl_getfield_pure_raw(self, box, fielddesc): tp = self.metainterp.cpu.typefor(fielddesc) - self.execute('getfield_raw', [box, ConstInt(offset)], tp, True) + self.execute('getfield_raw', [box, ConstInt(fielddesc)], tp, True) @arguments("box", "int", "box") - def opimpl_setfield_raw(self, box, offset, valuebox): - self.execute('setfield_raw', [box, ConstInt(offset), valuebox], 'void') + def opimpl_setfield_raw(self, box, fielddesc, valuebox): + self.execute('setfield_raw', [box, ConstInt(fielddesc), valuebox], + 'void') @arguments("bytecode", "varargs") def opimpl_call(self, callee, varargs): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Thu Feb 12 15:21:21 2009 @@ -47,8 +47,8 @@ self.check_loops(call_ptr=1, builtin=1) # 'len' remains else: # 'len' becomes a getfield('num_items') for now in lltype, - # which is itself encoded as a 'getfield__4' - self.check_loops(call_ptr=1, getfield_gc__4=1) + # which is itself encoded as a 'getfield_gc' + self.check_loops(call_ptr=1, getfield_gc=1) def test_send_to_single_target_method(self): myjitdriver = JitDriver(greens = [], reds = ['i', 'counter']) @@ -73,7 +73,7 @@ backendopt=True) assert res == 43 self.check_loops({'call_ptr': 1, 'guard_exception': 1, - 'getfield_gc__4': 1, + 'getfield_gc': 1, 'int_add': 1, 'merge_point' : 1, 'jump': 1, 'int_gt' : 1, 'guard_true' : 1, 'int_sub' : 1}) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Thu Feb 12 15:21:21 2009 @@ -75,14 +75,14 @@ ops = [ MergePoint('merge_point', [sum, fr], []), ResOperation('guard_nonvirtualized__4', [fr, ConstInt(ofs_node)], []), - ResOperation('getfield_gc_ptr', [fr, ConstInt(ofs_node)], [n1]), - ResOperation('getfield_gc__4', [n1, ConstInt(ofs_value)], [v]), + ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n1]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), ResOperation('new_with_vtable', [ConstInt(size_of_node), ConstAddr(node_vtable, cpu)], [n2]), - ResOperation('setfield_gc__4', [n2, ConstInt(ofs_value), v2], []), - ResOperation('setfield_gc_ptr', [fr, ConstInt(ofs_node), n2], []), + ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), + ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], []), Jump('jump', [sum2, fr], []), ] ops[1].desc = xy_desc Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Thu Feb 12 15:21:21 2009 @@ -29,8 +29,7 @@ assert res == 55 * 10 self.check_loop_count(1) self.check_loops(new=0, new_with_vtable=0, - getfield_gc__4=0, getfield_gc_ptr=0, - setfield_gc__4=0, setfield_gc_ptr=0) + getfield_gc=0, setfield_gc=0) def test_virtualized_2(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) @@ -55,8 +54,7 @@ assert res == 55 * 30 self.check_loop_count(1) self.check_loops(new=0, new_with_vtable=0, - getfield_gc__4=0, getfield_gc_ptr=0, - setfield_gc__4=0, setfield_gc_ptr=0) + getfield_gc=0, setfield_gc=0) def test_nonvirtual_obj_delays_loop(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) @@ -77,8 +75,7 @@ assert res == 640 self.check_loop_count(1) self.check_loops(new=0, new_with_vtable=0, - getfield_gc__4=0, getfield_gc_ptr=0, - setfield_gc__4=0, setfield_gc_ptr=0) + getfield_gc=0, setfield_gc=0) def test_two_loops_with_virtual(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) @@ -102,8 +99,7 @@ assert res == f(10) self.check_loop_count(2) self.check_loops(new=0, new_with_vtable=0, - getfield_gc__4=0, getfield_gc_ptr=0, - setfield_gc__4=0, setfield_gc_ptr=0) + getfield_gc=0, setfield_gc=0) def test_two_loops_with_escaping_virtual(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'node']) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Thu Feb 12 15:21:21 2009 @@ -31,7 +31,7 @@ xy.x = x + 1 n -= 1 self.meta_interp(f, [5]) - self.check_loops(getfield_gc__4=0, setfield_gc__4=0) + self.check_loops(getfield_gc=0, setfield_gc=0) def test_preexisting_access_2(self): def setup(): @@ -54,7 +54,7 @@ return xy.x res = self.meta_interp(f, [5]) assert res == 185 - self.check_loops(getfield__4=0, setfield__4=0) + self.check_loops(getfield_gc=0, setfield_gc=0) def test_two_paths_access(self): def setup(): @@ -74,7 +74,7 @@ return xy.x res = self.meta_interp(f, [18]) assert res == 10118 - self.check_loops(getfield__4=0, setfield__4=0) + self.check_loops(getfield_gc=0, setfield_gc=0) class ImplicitVirtualizableTests: @@ -100,7 +100,7 @@ res = self.meta_interp(f, [10], exceptions=False) assert res == 55 - self.check_loops(getfield__4=0, setfield__4=0) + self.check_loops(getfield_gc=0, setfield_gc=0) def test_external_read(self): py.test.skip("Fails") @@ -128,7 +128,7 @@ res = self.meta_interp(f, [123], exceptions=False, policy=StopAtXPolicy(g)) assert res == f(123) - self.check_loops(getfield_int=0, setfield_int=0) + self.check_loops(getfield_gc=0, setfield_gc=0) def test_external_write(self): py.test.skip("Fails") @@ -156,7 +156,7 @@ res = self.meta_interp(f, [240], exceptions=False, policy=StopAtXPolicy(g)) assert res == f(240) - self.check_loops(getfield_int=0, setfield_int=0) + self.check_loops(getfield_gc=0, setfield_gc=0) def test_list_implicit(self): class Frame(object): @@ -172,7 +172,7 @@ res = self.meta_interp(f, [53], exceptions=False) assert res == -6 - self.check_loops(getfield_ptr=0, setfield_ptr=0, call__4=0) + self.check_loops(getfield_gc=0, setfield_gc=0, call__4=0) def test_single_list_implicit(self): py.test.skip("in-progress") @@ -189,7 +189,7 @@ res = self.meta_interp(f, [53], exceptions=False) assert res == -17 - self.check_loops(getfield_ptr=0, setfield_ptr=0, call__4=0) + self.check_loops(getfield_gc=0, setfield_gc=0, call__4=0) ##class TestOOtype(ExplicitVirtualizableTests, From fijal at codespeak.net Thu Feb 12 15:43:59 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 15:43:59 +0100 (CET) Subject: [pypy-svn] r61786 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090212144359.A3116169EAD@codespeak.net> Author: fijal Date: Thu Feb 12 15:43:57 2009 New Revision: 61786 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Log: (arigo, fijal) First (very simple) test about virtualizables passes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 15:43:57 2009 @@ -5,7 +5,6 @@ class CancelInefficientLoop(Exception): pass - class FixedClassSpecNode(object): def __init__(self, known_class): self.known_class = known_class @@ -22,6 +21,17 @@ return False return instnode.cls.source.equals(self.known_class) +class VirtualizableSpecNode(FixedClassSpecNode): + def __init__(self, known_class, fields): + FixedClassSpecNode.__init__(self, known_class) + self.fields = fields + + def equals(self, other): + xxx + + def matches(self, instnode): + xxx + class VirtualInstanceSpecNode(FixedClassSpecNode): def __init__(self, known_class, fields): FixedClassSpecNode.__init__(self, known_class) @@ -58,7 +68,6 @@ return False return True - class AllocationStorage(object): def __init__(self): # allocations: list of vtables to allocate @@ -145,7 +154,7 @@ known_class = self.cls.source else: known_class = other.cls.source - if other.escaped: + if other.escaped and not other.virtualized: if self.cls is None: return None return FixedClassSpecNode(known_class) @@ -159,6 +168,8 @@ self.origfields[ofs] = InstanceNode(node.source.clonebox()) specnode = None fields.append((ofs, specnode)) + if other.escaped: + return VirtualizableSpecNode(known_class, fields) return VirtualInstanceSpecNode(known_class, fields) def adapt_to(self, specnode): @@ -267,9 +278,11 @@ if instnode.cls is None: instnode.cls = InstanceNode(op.args[1]) continue - elif opname.startswith('guard_nonvirtualized_'): + elif opname == 'guard_nonvirtualized': instnode = self.getnode(op.args[0]) instnode.virtualized = True + if instnode.cls is None: + instnode.cls = InstanceNode(op.args[1]) continue elif opname not in ('oois', 'ooisnot', 'ooisnull', 'oononnull'): @@ -319,7 +332,8 @@ instnode.cls = InstanceNode(specnode.known_class) else: assert instnode.cls.source.equals(specnode.known_class) - if isinstance(specnode, VirtualInstanceSpecNode): + if isinstance(specnode, (VirtualInstanceSpecNode, + VirtualizableSpecNode)): curfields = {} for ofs, subspecnode in specnode.fields: subinstnode = instnode.origfields[ofs] @@ -327,7 +341,8 @@ self.mutate_nodes(subinstnode, subspecnode) curfields[ofs] = subinstnode instnode.curfields = curfields - instnode.virtual = True + if isinstance(specnode, VirtualInstanceSpecNode): + instnode.virtual = True def expanded_version_of(self, boxlist): newboxlist = [] @@ -341,7 +356,8 @@ def expanded_version_of_rec(self, specnode, instnode, newboxlist): if not isinstance(specnode, VirtualInstanceSpecNode): newboxlist.append(instnode.source) - else: + if isinstance(specnode, (VirtualInstanceSpecNode, + VirtualizableSpecNode)): for ofs, subspecnode in specnode.fields: subinstnode = instnode.curfields[ofs] # should really be there self.expanded_version_of_rec(subspecnode, subinstnode, @@ -411,7 +427,7 @@ op = self.optimize_guard(op) newoperations.append(op) continue - elif opname.startswith('guard_nonvirtualized_'): + elif opname == 'guard_nonvirtualized': instnode = self.nodes[op.args[0]] if instnode.virtualized: continue Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Thu Feb 12 15:43:57 2009 @@ -5,9 +5,11 @@ from pypy.jit.metainterp import heaptracker from pypy.jit.metainterp.history import (ResOperation, MergePoint, Jump, ConstInt, ConstAddr, BoxInt, BoxPtr) -from pypy.jit.metainterp.optimize import PerfectSpecializer +from pypy.jit.metainterp.optimize import (PerfectSpecializer, + VirtualizableSpecNode) from pypy.jit.metainterp.virtualizable import VirtualizableDesc -from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable) +from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, + equaloplists) # ____________________________________________________________ @@ -55,8 +57,8 @@ # ____________________________________________________________ class A: - ofs_node = runner.CPU.offsetof(XY, 'node') - ofs_value = runner.CPU.offsetof(NODE, 'value') + ofs_node = runner.CPU.fielddescrof(XY, 'node') + ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) # frame = lltype.malloc(XY) @@ -74,7 +76,8 @@ sum2 = BoxInt(0 + frame.node.value) ops = [ MergePoint('merge_point', [sum, fr], []), - ResOperation('guard_nonvirtualized__4', [fr, ConstInt(ofs_node)], []), + ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), + ConstInt(ofs_node)], []), ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n1]), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), @@ -100,6 +103,7 @@ assert spec.nodes[A.fr].virtualized assert not spec.nodes[A.n1].escaped assert not spec.nodes[A.n2].escaped + assert isinstance(spec.specnodes[1], VirtualizableSpecNode) def test_A_optimize_loop(): operations = A.ops[:] @@ -108,8 +112,8 @@ spec.intersect_input_and_output() spec.optimize_loop() assert equaloplists(operations, [ - MergePoint('merge_point', [A.sum, A.n1, A.v], []), + MergePoint('merge_point', [A.sum, A.fr, A.v], []), ResOperation('int_sub', [A.v, ConstInt(1)], [A.v2]), ResOperation('int_add', [A.sum, A.v], [A.sum2]), - Jump('jump', [A.sum2, A.n1, A.v2], []), + Jump('jump', [A.sum2, A.fr, A.v2], []), ]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Thu Feb 12 15:43:57 2009 @@ -9,8 +9,8 @@ def __init__(self, cpu, TOPSTRUCT): "NOT_RPYTHON" initialize_virtualizable(cpu, TOPSTRUCT.access) - self.vable_base = cpu.offsetof(TOPSTRUCT, 'vable_base') - self.vable_rti = cpu.offsetof(TOPSTRUCT, 'vable_rti') + self.vable_base = cpu.fielddescrof(TOPSTRUCT, 'vable_base') + self.vable_rti = cpu.fielddescrof(TOPSTRUCT, 'vable_rti') self.c_vable_base = history.ConstInt(self.vable_base) self.c_vable_rti = history.ConstInt(self.vable_rti) @@ -32,7 +32,7 @@ if FIELDTYPE is lltype.Void: return type = history.getkind_num(cpu, FIELDTYPE) - ofs = cpu.offsetof(access.STRUCT, fieldname) + ofs = cpu.fielddescrof(access.STRUCT, fieldname) getset = access.getsets[fieldname] def getter(instanceptr): From fijal at codespeak.net Thu Feb 12 16:05:54 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 16:05:54 +0100 (CET) Subject: [pypy-svn] r61788 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090212150554.12E7C169E31@codespeak.net> Author: fijal Date: Thu Feb 12 16:05:53 2009 New Revision: 61788 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: (arigo, fijal) Pass the first virtualizable test, in simple enough case Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 16:05:53 2009 @@ -21,21 +21,20 @@ return False return instnode.cls.source.equals(self.known_class) -class VirtualizableSpecNode(FixedClassSpecNode): +class SpecNodeWithFields(FixedClassSpecNode): def __init__(self, known_class, fields): FixedClassSpecNode.__init__(self, known_class) self.fields = fields +class VirtualizableSpecNode(SpecNodeWithFields): + def equals(self, other): xxx def matches(self, instnode): xxx -class VirtualInstanceSpecNode(FixedClassSpecNode): - def __init__(self, known_class, fields): - FixedClassSpecNode.__init__(self, known_class) - self.fields = fields +class VirtualInstanceSpecNode(SpecNodeWithFields): def equals(self, other): if not isinstance(other, VirtualInstanceSpecNode): @@ -108,14 +107,14 @@ def extract_runtime_data(cpu, specnode, valuebox, resultlist): if not isinstance(specnode, VirtualInstanceSpecNode): resultlist.append(valuebox) - return - for ofs, subspecnode in specnode.fields: - cls = specnode.known_class.getint() - tp = cpu.typefor(ofs) - fieldbox = cpu.execute_operation('getfield_gc', - [valuebox, ConstInt(ofs)], - tp) - extract_runtime_data(cpu, subspecnode, fieldbox, resultlist) + if isinstance(specnode, SpecNodeWithFields): + for ofs, subspecnode in specnode.fields: + cls = specnode.known_class.getint() + tp = cpu.typefor(ofs) + fieldbox = cpu.execute_operation('getfield_gc', + [valuebox, ConstInt(ofs)], + tp) + extract_runtime_data(cpu, subspecnode, fieldbox, resultlist) class InstanceNode(object): @@ -332,8 +331,7 @@ instnode.cls = InstanceNode(specnode.known_class) else: assert instnode.cls.source.equals(specnode.known_class) - if isinstance(specnode, (VirtualInstanceSpecNode, - VirtualizableSpecNode)): + if isinstance(specnode, SpecNodeWithFields): curfields = {} for ofs, subspecnode in specnode.fields: subinstnode = instnode.origfields[ofs] @@ -356,8 +354,7 @@ def expanded_version_of_rec(self, specnode, instnode, newboxlist): if not isinstance(specnode, VirtualInstanceSpecNode): newboxlist.append(instnode.source) - if isinstance(specnode, (VirtualInstanceSpecNode, - VirtualizableSpecNode)): + if isinstance(specnode, SpecNodeWithFields): for ofs, subspecnode in specnode.fields: subinstnode = instnode.curfields[ofs] # should really be there self.expanded_version_of_rec(subspecnode, subinstnode, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 12 16:05:53 2009 @@ -402,43 +402,20 @@ @arguments("orgpc", "box", returns="box") def opimpl_guard_value(self, pc, box): - return self.implement_guard_value(pc, box) + self.implement_guard_value(pc, box) @arguments("orgpc", "box", returns="box") def opimpl_guard_class(self, pc, box): - obj = box.getptr(lltype.Ptr(rclass.OBJECT)) - cls = llmemory.cast_ptr_to_adr(obj.typeptr) - clsbox = ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) if isinstance(box, Box): + clsbox = self.cls_of_box(box) self.generate_guard(pc, 'guard_class', box, [clsbox]) - return clsbox - - @arguments("orgpc", "box", "virtualizabledesc", "int") - def opimpl_guard_nonvirtualized__1(self, pc, box, vdesc, guard_field): - self.execute('#virtualizabledesc', [box, vdesc], 'void', False) - self.generate_guard(pc, 'guard_nonvirtualized__1', box, - [ConstInt(guard_field)]) - @arguments("orgpc", "box", "virtualizabledesc", "int") - def opimpl_guard_nonvirtualized__2(self, pc, box, vdesc, guard_field): - self.execute('#virtualizabledesc', [box, vdesc], 'void', False) - self.generate_guard(pc, 'guard_nonvirtualized__2', box, - [ConstInt(guard_field)]) - @arguments("orgpc", "box", "virtualizabledesc", "int") - def opimpl_guard_nonvirtualized__4(self, pc, box, vdesc, guard_field): - self.execute('#virtualizabledesc', [box, vdesc], 'void', False) - self.generate_guard(pc, 'guard_nonvirtualized__4', box, - [ConstInt(guard_field)]) - @arguments("orgpc", "box", "virtualizabledesc", "int") - def opimpl_guard_nonvirtualized__8(self, pc, box, vdesc, guard_field): - self.execute('#virtualizabledesc', [box, vdesc], 'void', False) - self.generate_guard(pc, 'guard_nonvirtualized__8', box, - [ConstInt(guard_field)]) @arguments("orgpc", "box", "virtualizabledesc", "int") - def opimpl_guard_nonvirtualized_ptr(self, pc, box, vdesc, guard_field): - self.execute('#virtualizabledesc', [box, vdesc], 'void', False) - self.generate_guard(pc, 'guard_nonvirtualized_ptr', box, - [ConstInt(guard_field)]) + def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): + clsbox = self.cls_of_box(box) + op = self.generate_guard(pc, 'guard_nonvirtualized', box, + [clsbox, ConstInt(guard_field)]) + op.desc = vdesc @arguments("box") def opimpl_keepalive(self, box): @@ -548,6 +525,7 @@ self.pc = pc guard_op.key = self.metainterp.record_state() self.pc = saved_pc + return guard_op def implement_guard_value(self, pc, box): if isinstance(box, Box): @@ -557,6 +535,11 @@ else: return box # no promotion needed, already a Const + def cls_of_box(self, box): + obj = box.getptr(lltype.Ptr(rclass.OBJECT)) + cls = llmemory.cast_ptr_to_adr(obj.typeptr) + return ConstInt(self.metainterp.cpu.cast_adr_to_int(cls)) + def follow_jump(self): self.pc -= 3 self.pc = self.load_3byte() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Thu Feb 12 16:05:53 2009 @@ -88,7 +88,7 @@ ResOperation('setfield_gc', [fr, ConstInt(ofs_node), n2], []), Jump('jump', [sum2, fr], []), ] - ops[1].desc = xy_desc + ops[1].vdesc = xy_desc def test_A_find_nodes(): spec = PerfectSpecializer(A.ops) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Thu Feb 12 16:05:53 2009 @@ -5,6 +5,7 @@ from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR +from pypy.jit.metainterp.test.test_vable_optimize import XY, xy_vtable promote_virtualizable = lloperation.llop.promote_virtualizable debug_print = lloperation.llop.debug_print @@ -19,6 +20,7 @@ def setup(): xy = lltype.malloc(XY) xy.vable_rti = lltype.nullptr(VABLERTIPTR.TO) + xy.parent.typeptr = xy_vtable return xy def f(n): xy = setup() From arigo at codespeak.net Thu Feb 12 16:26:36 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 16:26:36 +0100 (CET) Subject: [pypy-svn] r61790 - in pypy/branch/pyjitpl5/pypy/rpython: . lltypesystem Message-ID: <20090212152636.01016169E72@codespeak.net> Author: arigo Date: Thu Feb 12 16:26:36 2009 New Revision: 61790 Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/opimpl.py Log: Move promote_virtualizable from llinterp.py to opimpl.py, to make it runnable. Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Thu Feb 12 16:26:36 2009 @@ -532,9 +532,6 @@ def op_jit_marker(self, *args): pass - def op_promote_virtualizable(self, object, fieldname): - pass # XXX should do something - def op_instrument_count(self, ll_tag, ll_label): pass # xxx for now Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py Thu Feb 12 16:26:36 2009 @@ -129,7 +129,10 @@ def specialize_call(self, hop): op = self.instance # the LLOp object that was called args_v = [hop.inputarg(r, i+1) for i, r in enumerate(hop.args_r[1:])] - hop.exception_is_here() + if op.canraise: + hop.exception_is_here() + else: + hop.exception_cannot_occur() return hop.genop(op.opname, args_v, resulttype=hop.r_result.lowleveltype) Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/opimpl.py Thu Feb 12 16:26:36 2009 @@ -386,6 +386,9 @@ print arg, print +def op_promote_virtualizable(object, fieldname): + pass # XXX should do something + # ____________________________________________________________ def get_op_impl(opname): From fijal at codespeak.net Thu Feb 12 16:32:37 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 16:32:37 +0100 (CET) Subject: [pypy-svn] r61791 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090212153237.E71E7169E99@codespeak.net> Author: fijal Date: Thu Feb 12 16:32:35 2009 New Revision: 61791 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: (arigo, fijal) Correctly handle guard failure with virtualizables around Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 16:32:35 2009 @@ -71,9 +71,14 @@ def __init__(self): # allocations: list of vtables to allocate # setfields: list of triples - # (index_in_allocations, ofs, index_in_arglist) + # (index_in_allocations, ofs, ~index_in_arglist) # -or- - # (index_in_allocations, ofs, ~index_in_allocations) + # (index_in_allocations, ofs, index_in_allocations) + # -or- + # (~index_in_arglist, ofs, index_in_allocations) + # -or- + # (~index_in_arglist, ofs, ~index_in_arglist) + # last two cases are for virtualizables only self.allocations = [] self.setfields = [] @@ -82,19 +87,28 @@ return memo[box] if isinstance(box, Const): virtual = False + virtualized = False else: instnode = nodes[box] virtual = instnode.virtual + virtualized = instnode.virtualized if virtual: alloc_offset = len(self.allocations) self.allocations.append(instnode.cls.source.getint()) - res = ~alloc_offset + res = alloc_offset memo[box] = res for ofs, node in instnode.curfields.items(): num = self.deal_with_box(node.source, nodes, liveboxes, memo) self.setfields.append((alloc_offset, ofs, num)) + elif virtualized: + res = ~len(liveboxes) + memo[box] = res + liveboxes.append(box) + for ofs, node in instnode.curfields.items(): + num = self.deal_with_box(node.source, nodes, liveboxes, memo) + self.setfields.append((res, ofs, num)) else: - res = len(liveboxes) + res = ~len(liveboxes) memo[box] = res liveboxes.append(box) return res @@ -546,18 +560,20 @@ allocated_boxes.append(instbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: if index_in_arglist < 0: - fieldbox = allocated_boxes[~index_in_arglist] + fieldbox = boxes_from_frame[~index_in_arglist] + else: + fieldbox = allocated_boxes[index_in_arglist] + if index_in_alloc < 0: + box = boxes_from_frame[~index_in_alloc] else: - fieldbox = boxes_from_frame[index_in_arglist] - vtable = storage.allocations[index_in_alloc] - box = allocated_boxes[index_in_alloc] + box = allocated_boxes[index_in_alloc] history.execute_and_record('setfield_gc', [box, ConstInt(ofs), fieldbox], 'void', False) newboxes = [] for index in storage.indices: if index < 0: - newboxes.append(allocated_boxes[~index]) + newboxes.append(boxes_from_frame[~index]) else: - newboxes.append(boxes_from_frame[index]) + newboxes.append(allocated_boxes[index]) return newboxes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 12 16:32:35 2009 @@ -415,7 +415,8 @@ clsbox = self.cls_of_box(box) op = self.generate_guard(pc, 'guard_nonvirtualized', box, [clsbox, ConstInt(guard_field)]) - op.desc = vdesc + if op: + op.desc = vdesc @arguments("box") def opimpl_keepalive(self, box): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Thu Feb 12 16:32:35 2009 @@ -296,7 +296,7 @@ assert guard_op.liveboxes == [E.sum2, E.v2] vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] - assert guard_op.storage_info.setfields == [(0, E.ofs_value, 1)] + assert guard_op.storage_info.setfields == [(0, E.ofs_value, -2)] def test_E_rebuild_after_failure(): class FakeHistory(object): @@ -425,7 +425,7 @@ assert guard_op.liveboxes == [G.sum2, ConstInt(124)] vt = cpu.cast_adr_to_int(node_vtable_adr) assert guard_op.storage_info.allocations == [vt] - assert guard_op.storage_info.setfields == [(0, G.ofs_value, 1)] + assert guard_op.storage_info.setfields == [(0, G.ofs_value, -2)] # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Thu Feb 12 16:32:35 2009 @@ -14,16 +14,21 @@ class ExplicitVirtualizableTests: + def _freeze_(self): + return True + + @staticmethod + def setup(): + xy = lltype.malloc(XY) + xy.vable_rti = lltype.nullptr(VABLERTIPTR.TO) + xy.parent.typeptr = xy_vtable + return xy + def test_preexisting_access(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], virtualizables = ['xy']) - def setup(): - xy = lltype.malloc(XY) - xy.vable_rti = lltype.nullptr(VABLERTIPTR.TO) - xy.parent.typeptr = xy_vtable - return xy def f(n): - xy = setup() + xy = self.setup() xy.x = 10 while n > 0: myjitdriver.can_enter_jit(xy=xy, n=n) @@ -32,26 +37,28 @@ x = xy.x xy.x = x + 1 n -= 1 - self.meta_interp(f, [5]) + return xy.x + res = self.meta_interp(f, [20]) + assert res == 30 self.check_loops(getfield_gc=0, setfield_gc=0) def test_preexisting_access_2(self): - def setup(): - xy = lltype.malloc(XY) - xy.vable_rti = lltype.nullptr(VABLERTIPTR.TO) - return xy + myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], + virtualizables = ['xy']) def f(n): - xy = setup() + xy = self.setup() xy.x = 100 - while n > 0: - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x - xy.x = x + 1 - n -= 1 while n > -8: - promote_virtualizable(lltype.Void, xy, 'x') - x = xy.x - xy.x = x + 10 + myjitdriver.can_enter_jit(xy=xy, n=n) + myjitdriver.jit_merge_point(xy=xy, n=n) + if n > 0: + promote_virtualizable(lltype.Void, xy, 'x') + x = xy.x + xy.x = x + 1 + else: + promote_virtualizable(lltype.Void, xy, 'x') + x = xy.x + xy.x = x + 10 n -= 1 return xy.x res = self.meta_interp(f, [5]) From fijal at codespeak.net Thu Feb 12 16:40:57 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 16:40:57 +0100 (CET) Subject: [pypy-svn] r61792 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090212154057.E36C0168430@codespeak.net> Author: fijal Date: Thu Feb 12 16:40:57 2009 New Revision: 61792 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: (arigo, fijal) Pass another test form test_virtualizable by having a correct inheritance (still a bit broken, but needs further tests) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 16:40:57 2009 @@ -26,20 +26,8 @@ FixedClassSpecNode.__init__(self, known_class) self.fields = fields -class VirtualizableSpecNode(SpecNodeWithFields): - def equals(self, other): - xxx - - def matches(self, instnode): - xxx - -class VirtualInstanceSpecNode(SpecNodeWithFields): - - def equals(self, other): - if not isinstance(other, VirtualInstanceSpecNode): - return False - elif not self.known_class.equals(other.known_class): + if not self.known_class.equals(other.known_class): return False elif len(self.fields) != len(other.fields): return False @@ -58,6 +46,7 @@ return True def matches(self, instnode): + # XXX think about details of virtual vs virtualizable if not FixedClassSpecNode.matches(self, instnode): return False for key, value in self.fields: @@ -67,6 +56,20 @@ return False return True +class VirtualizableSpecNode(SpecNodeWithFields): + + def equals(self, other): + if not isinstance(other, VirtualizableSpecNode): + return False + return SpecNodeWithFields.equals(self, other) + +class VirtualInstanceSpecNode(SpecNodeWithFields): + + def equals(self, other): + if not isinstance(other, VirtualInstanceSpecNode): + return False + return SpecNodeWithFields.equals(self, other) + class AllocationStorage(object): def __init__(self): # allocations: list of vtables to allocate From fijal at codespeak.net Thu Feb 12 16:46:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 16:46:58 +0100 (CET) Subject: [pypy-svn] r61793 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090212154658.7A91F169EAC@codespeak.net> Author: fijal Date: Thu Feb 12 16:46:56 2009 New Revision: 61793 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: (arigo, fijal) Fix tests that we want to pass by now Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Thu Feb 12 16:46:56 2009 @@ -66,14 +66,14 @@ self.check_loops(getfield_gc=0, setfield_gc=0) def test_two_paths_access(self): - def setup(): - xy = lltype.malloc(XY) - xy.vable_rti = lltype.nullptr(VABLERTIPTR.TO) - return xy + myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'], + virtualizables = ['xy']) def f(n): - xy = setup() + xy = self.setup() xy.x = 100 while n > 0: + myjitdriver.can_enter_jit(xy=xy, n=n) + myjitdriver.jit_merge_point(xy=xy, n=n) promote_virtualizable(lltype.Void, xy, 'x') x = xy.x if n <= 10: @@ -89,6 +89,9 @@ class ImplicitVirtualizableTests: def test_simple_implicit(self): + myjitdriver = JitDriver(greens = [], reds = ['frame'], + virtualizables = ['frame']) + class Frame(object): _virtualizable2_ = True def __init__(self, x, y): @@ -103,11 +106,13 @@ frame = Frame(n, 0) somewhere_else.top_frame = frame # escapes while frame.x > 0: + myjitdriver.can_enter_jit(frame=frame) + myjitdriver.jit_merge_point(frame=frame) frame.y += frame.x frame.x -= 1 return somewhere_else.top_frame.y - res = self.meta_interp(f, [10], exceptions=False) + res = self.meta_interp(f, [10]) assert res == 55 self.check_loops(getfield_gc=0, setfield_gc=0) @@ -168,6 +173,7 @@ self.check_loops(getfield_gc=0, setfield_gc=0) def test_list_implicit(self): + py.test.skip("in-progress") class Frame(object): _virtualizable2_ = True From fijal at codespeak.net Thu Feb 12 17:23:47 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 17:23:47 +0100 (CET) Subject: [pypy-svn] r61794 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090212162347.73F80169E51@codespeak.net> Author: fijal Date: Thu Feb 12 17:23:47 2009 New Revision: 61794 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: (arigo, fijal) A test and a fix for variables that are only read or only write into virtualizable Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 17:23:47 2009 @@ -174,19 +174,39 @@ if self.cls is None: return None return FixedClassSpecNode(known_class) - fields = [] - lst = other.curfields.items() - lst.sort() - for ofs, node in lst: - if ofs in self.origfields: - specnode = self.origfields[ofs].intersect(node) - else: - self.origfields[ofs] = InstanceNode(node.source.clonebox()) - specnode = None - fields.append((ofs, specnode)) - if other.escaped: + if not other.escaped: + fields = [] + lst = other.curfields.items() + lst.sort() + for ofs, node in lst: + if ofs in self.origfields: + specnode = self.origfields[ofs].intersect(node) + else: + self.origfields[ofs] = InstanceNode(node.source.clonebox()) + specnode = None + fields.append((ofs, specnode)) + return VirtualInstanceSpecNode(known_class, fields) + else: + assert self is other + d = self.origfields.copy() + d.update(other.curfields) + offsets = d.keys() + offsets.sort() + fields = [] + for ofs in offsets: + if ofs in self.origfields and ofs in other.curfields: + node = other.curfields[ofs] + specnode = self.origfields[ofs].intersect(node) + elif ofs in self.origfields: + specnode = None + else: + # ofs in other.curfields + node = other.curfields[ofs] + self.origfields[ofs] = InstanceNode(node.source.clonebox()) + specnode = None + fields.append((ofs, specnode)) + return VirtualizableSpecNode(known_class, fields) - return VirtualInstanceSpecNode(known_class, fields) def adapt_to(self, specnode): if not isinstance(specnode, VirtualInstanceSpecNode): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 12 17:23:47 2009 @@ -406,9 +406,10 @@ @arguments("orgpc", "box", returns="box") def opimpl_guard_class(self, pc, box): + clsbox = self.cls_of_box(box) if isinstance(box, Box): - clsbox = self.cls_of_box(box) self.generate_guard(pc, 'guard_class', box, [clsbox]) + return clsbox @arguments("orgpc", "box", "virtualizabledesc", "int") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Thu Feb 12 17:23:47 2009 @@ -6,7 +6,8 @@ from pypy.jit.metainterp.history import (ResOperation, MergePoint, Jump, ConstInt, ConstAddr, BoxInt, BoxPtr) from pypy.jit.metainterp.optimize import (PerfectSpecializer, - VirtualizableSpecNode) + VirtualizableSpecNode, + VirtualInstanceSpecNode) from pypy.jit.metainterp.virtualizable import VirtualizableDesc from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, equaloplists) @@ -117,3 +118,39 @@ ResOperation('int_add', [A.sum, A.v], [A.sum2]), Jump('jump', [A.sum2, A.fr, A.v2], []), ]) + +# ____________________________________________________________ + +class B: + ofs_node = runner.CPU.fielddescrof(XY, 'node') + ofs_value = runner.CPU.fielddescrof(NODE, 'value') + size_of_node = runner.CPU.sizeof(NODE) + # + frame = lltype.malloc(XY) + frame.vable_rti = lltype.nullptr(XY.vable_rti.TO) + frame.node = lltype.malloc(NODE) + frame.node.value = 20 + fr = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame)) + n1 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + v = BoxInt(13) + ops = [ + MergePoint('merge_point', [fr], []), + ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), + ConstInt(ofs_node)], []), + ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n1]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + Jump('jump', [fr], []), + ] + ops[1].vdesc = xy_desc + +def test_B_intersect_input_and_output(): + spec = PerfectSpecializer(B.ops) + spec.find_nodes() + spec.intersect_input_and_output() + assert spec.nodes[B.fr].escaped + assert spec.nodes[B.fr].virtualized + assert not spec.nodes[B.n1].escaped + assert isinstance(spec.specnodes[0], VirtualizableSpecNode) + assert len(spec.specnodes[0].fields) == 1 + assert spec.specnodes[0].fields[0][0] == B.ofs_node + assert spec.specnodes[0].fields[0][1] is None From fijal at codespeak.net Thu Feb 12 17:27:49 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 17:27:49 +0100 (CET) Subject: [pypy-svn] r61795 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090212162749.861F2169EB2@codespeak.net> Author: fijal Date: Thu Feb 12 17:27:45 2009 New Revision: 61795 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Log: (arigo, fijal) experimental - add a _virtualizable2_ arg to Stack Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Thu Feb 12 17:27:45 2009 @@ -11,6 +11,8 @@ return t class Stack(object): + _virtualizable2_ = True + def __init__(self, size): self.stack = [0] * size self.stackpos = 0 From antocuni at codespeak.net Thu Feb 12 17:28:11 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 12 Feb 2009 17:28:11 +0100 (CET) Subject: [pypy-svn] r61796 - pypy/branch/oo-jit/pypy/jit/codegen/cli Message-ID: <20090212162811.A4AB3169EB4@codespeak.net> Author: antocuni Date: Thu Feb 12 17:28:11 2009 New Revision: 61796 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Log: ops, this should have been checked in with r61783 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Thu Feb 12 17:28:11 2009 @@ -2,7 +2,7 @@ from pypy.rlib.objectmodel import specialize from pypy.rlib.rarithmetic import intmask from pypy.rpython.ootypesystem import ootype -from pypy.translator.cli.dotnet import CLR, typeof, new_array +from pypy.translator.cli.dotnet import CLR, typeof, new_array, init_array from pypy.translator.cli import opcodes as cli_opcodes System = CLR.System OpCodes = System.Reflection.Emit.OpCodes @@ -453,10 +453,12 @@ elif step is cli_opcodes.StoreResult: body.append('self.storeResult()') elif isinstance(step, str): - if 'call' in step: - return # XXX, fix this - attrname = opcode2attrname(step) - body.append('self.meth.il.Emit(OpCodes.%s)' % attrname) + if step.startswith('call '): + signature = step[len('call '):] + renderCall(body, signature) + else: + attrname = opcode2attrname(step) + body.append('self.meth.il.Emit(OpCodes.%s)' % attrname) elif isinstance(step, cli_opcodes.MapException): # MapException is supported only if it's the only element of the # instr list, look inside RenderOp @@ -500,6 +502,32 @@ else: assert False, 'Unknown exception type' +def renderCall(body, signature): + # signature is like this: + # int64 class [mscorlib]System.Foo::Bar(int64, int32) + + typenames = { + 'int32': 'System.Int32', + 'int64': 'System.Int64', + 'float64': 'System.Double', + } + + restype, _, signature = signature.split(' ', 3) + assert signature.startswith('[mscorlib]'), 'external assemblies '\ + 'not supported' + signature = signature[len('[mscorlib]'):] + typename, signature = signature.split('::') + methname, signature = signature.split('(') + assert signature.endswith(')') + params = signature[:-1].split(',') + params = map(str.strip, params) + params = [typenames.get(p, p) for p in params] + params = ['typeof(%s)' % p for p in params] + + body.append("t = System.Type.GetType('%s')" % typename) + body.append("params = init_array(System.Type, %s)" % ', '.join(params)) + body.append("methinfo = t.GetMethod('%s', params)" % methname) + body.append("self.meth.il.Emit(OpCodes.Call, methinfo)") UNARYOPS = fillops(cli_opcodes.unary_ops, "UnaryOp") BINARYOPS = fillops(cli_opcodes.binary_ops, "BinaryOp") From antocuni at codespeak.net Thu Feb 12 17:29:09 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 12 Feb 2009 17:29:09 +0100 (CET) Subject: [pypy-svn] r61797 - in pypy/branch/oo-jit/pypy/jit/codegen/cli: . test Message-ID: <20090212162909.651D5169EB2@codespeak.net> Author: antocuni Date: Thu Feb 12 17:29:08 2009 New Revision: 61797 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Log: autogen operations that involves a call to a method, like int_abs & co. Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Thu Feb 12 17:29:08 2009 @@ -812,9 +812,14 @@ gv_res = op.gv_res() return gv_res -## @specialize.arg(1) -## def genraisingop1(self, opname, gv_arg): -## return a pair (gv_result, gv_flag_set_if_exception) + @specialize.arg(1) + def genraisingop1(self, opname, gv_arg): + opcls = ops.getopclass1(opname) + op = opcls(self.meth, gv_arg) + self.appendop(op) + gv_res = op.gv_res() + gv_excflag = op.gv_excflag() + return gv_res, gv_excflag @specialize.arg(1) def genraisingop2(self, opname, gv_arg1, gv_arg2): Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Thu Feb 12 17:29:08 2009 @@ -69,18 +69,6 @@ def test_longwinded_and_direct(self): py.test.skip('mono 2.2 crashes') - def test_ovfcheck1_direct(self): - import sys - # XXX: this test is partly copied from rgenop_tests, because - # int_abs_ovf is not yet supported. Delete this method as soon as it - # is - yield self.ovfcheck1_direct, "int_neg_ovf", [(18, -18), - (-18, 18), - (sys.maxint, -sys.maxint), - (-sys.maxint, sys.maxint), - (-sys.maxint-1, None)] - - def test_cast_direct(self): py.test.skip('fixme') From arigo at codespeak.net Thu Feb 12 17:32:49 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 17:32:49 +0100 (CET) Subject: [pypy-svn] r61798 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090212163249.51247169E1F@codespeak.net> Author: arigo Date: Thu Feb 12 17:32:48 2009 New Revision: 61798 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: * Improve display of GraphOps. * Small fix (?) in optimize.py. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Thu Feb 12 17:32:48 2009 @@ -329,6 +329,12 @@ op.key = self.key return op + def __repr__(self): + result = ResOperation.__repr__(self) + if hasattr(self, 'liveboxes'): + result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes))) + return result + # ____________________________________________________________ # The Graph class is to store a loop or a bridge. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 17:32:48 2009 @@ -221,6 +221,7 @@ if self.startbox: flags += 's' if self.const: flags += 'c' if self.virtual: flags += 'v' + if self.virtualized: flags += 'V' return "" % (self.source, flags) @@ -316,7 +317,8 @@ continue elif opname == 'guard_nonvirtualized': instnode = self.getnode(op.args[0]) - instnode.virtualized = True + if instnode.startbox: + instnode.virtualized = True if instnode.cls is None: instnode.cls = InstanceNode(op.args[1]) continue From afa at codespeak.net Thu Feb 12 17:57:19 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 12 Feb 2009 17:57:19 +0100 (CET) Subject: [pypy-svn] r61799 - pypy/trunk/pypy/lib/_ctypes Message-ID: <20090212165719.E495A169E9D@codespeak.net> Author: afa Date: Thu Feb 12 17:57:16 2009 New Revision: 61799 Modified: pypy/trunk/pypy/lib/_ctypes/function.py Log: Great progress toward a usable comtypes module on pypy: our ctypes module can now call COM functions and methods. Support for OUT parameters has been added, it's probably incomplete. Next: support the _type_='X' (BSTR) objects. Everything in pure python: _rawffi really rocks. Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Thu Feb 12 17:57:16 2009 @@ -31,6 +31,10 @@ callable = None _ptr = None _buffer = None + # win32 COM properties + _paramflags = None + _com_index = None + _com_iid = None def _getargtypes(self): return self._argtypes_ @@ -70,11 +74,13 @@ argument = args[0] if isinstance(argument, (int, long)): + # direct construction from raw address ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._ptr = _rawffi.FuncPtr(argument, ffiargs, ffires, self._flags_) self._buffer = self._ptr.byptr() elif callable(argument): + # A callback into python self.callable = argument ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._ptr = _rawffi.CallbackPtr(self._wrap_callable(argument, @@ -82,6 +88,7 @@ ffiargs, ffires) self._buffer = self._ptr.byptr() elif isinstance(argument, tuple) and len(argument) == 2: + # function exported from a shared library import ctypes self.name, self.dll = argument if isinstance(self.dll, str): @@ -90,12 +97,23 @@ ptr = self._getfuncptr([], ctypes.c_int) self._buffer = ptr.byptr() + elif (sys.platform == 'win32' and + len(args) >= 2 and isinstance(args[0], (int, long))): + # A COM function call, by index + ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) + self._com_index = args[0] + 0x1000 + self.name = args[1] + if len(args) > 2: + self._paramflags = args[2] + # XXX ignored iid = args[3] + elif len(args) == 0: + # Empty function object. # this is needed for casts self._buffer = _rawffi.Array('P')(1) return else: - raise TypeError("Unknown constructor %s" % (argument,)) + raise TypeError("Unknown constructor %s" % (args,)) def _wrap_callable(self, to_call, argtypes): def f(*args): @@ -118,25 +136,26 @@ return res return argtypes = self._argtypes_ + + if self._com_index: + from ctypes import cast, c_void_p, POINTER + thisarg = cast(args[0], POINTER(POINTER(c_void_p))).contents + argtypes = [c_void_p] + list(argtypes) + args = list(args) + args[0] = args[0].value + else: + thisarg = None + if argtypes is None: argtypes = self._guess_argtypes(args) - else: - dif = len(args) - len(argtypes) - if dif < 0: - raise TypeError("Not enough arguments") - if dif > 0: - cut = len(args) - dif - argtypes = argtypes[:] + self._guess_argtypes(args[cut:]) + argtypes, argsandobjs = self._wrap_args(argtypes, args) + restype = self._restype_ - funcptr = self._getfuncptr(argtypes, restype) - argsandobjs = self._wrap_args(argtypes, args) + funcptr = self._getfuncptr(argtypes, restype, thisarg) resbuffer = funcptr(*[arg._buffer for _, arg in argsandobjs]) - if restype is not None: - if not isinstance(restype, _CDataMeta): - return restype(resbuffer[0]) - return restype._CData_retval(resbuffer) + return self._build_result(restype, resbuffer, argtypes, argsandobjs) - def _getfuncptr(self, argtypes, restype): + def _getfuncptr(self, argtypes, restype, thisarg=None): if self._ptr is not None: return self._ptr if restype is None or not isinstance(restype, _CDataMeta): @@ -151,6 +170,11 @@ self._ptr = ptr return ptr + if self._com_index: + # extract the address from the object's virtual table + ptr = thisarg[self._com_index - 0x1000] + return _rawffi.FuncPtr(ptr, argshapes, resshape, self._flags_) + cdll = self.dll._handle try: return cdll.ptr(self.name, argshapes, resshape, self._flags_) @@ -196,11 +220,70 @@ return res def _wrap_args(self, argtypes, args): - try: - return [argtype._CData_input(arg) for argtype, arg in - zip(argtypes, args)] - except (UnicodeError, TypeError), e: - raise ArgumentError(str(e)) + wrapped_args = [] + consumed = 0 + for i, argtype in enumerate(argtypes): + if i > 0 and self._paramflags is not None: + idlflag, name = self._paramflags[i-1] + if idlflag == 2: # OUT + import ctypes + arg = ctypes.byref(argtype._type_()) + wrapped_args.append((arg, arg)) + continue + + if consumed == len(args): + raise TypeError("Not enough arguments") + arg = args[consumed] + try: + wrapped = argtype._CData_input(arg) + except (UnicodeError, TypeError), e: + raise ArgumentError(str(e)) + wrapped_args.append(wrapped) + consumed += 1 + + if len(wrapped_args) < len(args): + extra = args[len(wrapped_args):] + extra_types = self._guess_argtypes(extra) + for arg, argtype in zip(extra, extra_types): + try: + wrapped = argtype._CData_input(arg) + except (UnicodeError, TypeError), e: + raise ArgumentError(str(e)) + wrapped_args.append(wrapped) + argtypes.extend(extra_types) + return argtypes, wrapped_args + + def _build_result(self, restype, resbuffer, argtypes, argsandobjs): + """Build the function result: + If there is no OUT parameter, return the actual function result + If there is one OUT parameter, return it + If there are many OUT parameters, return a tuple""" + results = [] + if self._paramflags: + for argtype, (_, obj), paramflag in zip(argtypes[1:], argsandobjs[1:], + self._paramflags): + idlflag, name = paramflag + if idlflag == 2: # OUT + val = obj.contents + + # XXX find a better way to detect pointers to pointers + basetype = argtype._type_._type_ + if isinstance(basetype, str) and basetype != 'P': + val = val.value + + results.append(val) + + if results: + if len(results) == 1: + return results[0] + else: + return tuple(results) + + # No output parameter, return the actual function result. + if restype is not None: + if not isinstance(restype, _CDataMeta): + return restype(resbuffer[0]) + return restype._CData_retval(resbuffer) def __del__(self): if self._needs_free: From arigo at codespeak.net Thu Feb 12 17:57:50 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 17:57:50 +0100 (CET) Subject: [pypy-svn] r61800 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090212165750.E7B65169EA7@codespeak.net> Author: arigo Date: Thu Feb 12 17:57:49 2009 New Revision: 61800 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Log: (fijal, arigo) Comment out (we no longer use hint). Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Feb 12 17:57:49 2009 @@ -387,14 +387,14 @@ serialize_op_unichar_eq = serialize_op_char_eq serialize_op_unichar_ne = serialize_op_char_ne - def serialize_op_hint(self, op): - hints = op.args[1].value - if hints.get('promote') and op.args[0].concretetype is not lltype.Void: - self.minimize_variables() - self.emit('guard_value', self.var_position(op.args[0])) - self.register_var(op.result) - else: - self.serialize_op_same_as(op) +## def serialize_op_hint(self, op): +## hints = op.args[1].value +## if hints.get('promote') and op.args[0].concretetype is not lltype.Void: +## self.minimize_variables() +## self.emit('guard_value', self.var_position(op.args[0])) +## self.register_var(op.result) +## else: +## self.serialize_op_same_as(op) def serialize_op_int_is_true(self, op): if isinstance(op.args[0], Constant): From arigo at codespeak.net Thu Feb 12 17:58:09 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 17:58:09 +0100 (CET) Subject: [pypy-svn] r61801 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090212165809.3E6CC169E9D@codespeak.net> Author: arigo Date: Thu Feb 12 17:58:08 2009 New Revision: 61801 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Log: (fijal, arigo) Test and fix for exceptions. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Feb 12 17:58:08 2009 @@ -75,7 +75,8 @@ 'guard_false' : (('bool',), None), 'guard_value' : (('int', 'int'), None), 'guard_class' : (('ptr', 'ptr'), None), - 'guard_exception' : (('ptr',), None), + 'guard_no_exception' : ((), None), + 'guard_exception' : (('ptr',), 'ptr'), 'guard_nonvirtualized__4' : (('ptr', 'int'), None), 'newstr' : (('int',), 'ptr'), 'strlen' : (('ptr',), 'int'), @@ -616,20 +617,24 @@ op_guard_nonvirtualized_ptr = op_guard_nonvirtualized__4 + def op_guard_no_exception(self): + if self.last_exception: + self.last_exception_handled = True + raise GuardFailed + def op_guard_exception(self, expected_exception): expected_exception = llmemory.cast_adr_to_ptr( self.cpu.cast_int_to_adr(expected_exception), rclass.CLASSTYPE) + assert expected_exception if self.last_exception: got = self.last_exception.args[0] self.last_exception_handled = True - if not expected_exception: - raise GuardFailed if not rclass.ll_issubclass(got, expected_exception): raise GuardFailed + return self.last_exception.args[1] else: - if expected_exception: - raise GuardFailed + raise GuardFailed def op_new(self, typesize): TYPE = symbolic.Size2Type[typesize] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 12 17:58:08 2009 @@ -693,7 +693,8 @@ def handle_guard_failure(self, guard_failure): orig_boxes = self.initialize_state_from_guard_failure(guard_failure) try: - if guard_failure.guard_op.opname == 'guard_exception': + if guard_failure.guard_op.opname in ['guard_exception', + 'guard_no_exception']: self.raise_exception_upon_guard_failure(guard_failure) self.interpret() assert False, "should always raise" @@ -816,14 +817,17 @@ self.handle_exception(etype, evalue) def handle_exception(self, etype, evalue): - exception_box = ConstInt(etype) frame = self.framestack[-1] - frame.generate_guard(frame.pc, 'guard_exception', - None, [exception_box]) if etype: + exception_box = ConstInt(etype) exc_value_box = BoxPtr(evalue) + op = frame.generate_guard(frame.pc, 'guard_exception', + None, [exception_box]) + if op: + op.results = [exc_value_box] return self.finishframe_exception(exception_box, exc_value_box) else: + frame.generate_guard(frame.pc, 'guard_no_exception', None, []) return False ## def forced_vars_after_guard_failure(self, guard_failure): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Thu Feb 12 17:58:08 2009 @@ -9,17 +9,17 @@ def test_simple(self): def g(n): if n <= 0: - raise IndexError + raise MyError(n) return n - 1 def f(n): try: return g(n) - except IndexError: - return 5 + except MyError, e: + return e.n + 10 res = self.interp_operations(f, [9]) assert res == 8 res = self.interp_operations(f, [-99]) - assert res == 5 + assert res == -89 def test_no_exception(self): myjitdriver = JitDriver(greens = [], reds = ['n']) @@ -81,16 +81,17 @@ myjitdriver = JitDriver(greens = [], reds = ['n']) def check(n): if n > -100: - raise IndexError + raise MyError(n) def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) try: check(n) - except IndexError: - n = n - 5 + except MyError, e: + n = e.n - 5 return n + assert f(53) == -2 res = self.meta_interp(f, [53], policy=StopAtXPolicy(check)) assert res == -2 @@ -177,7 +178,7 @@ myjitdriver = JitDriver(greens = [], reds = ['n']) def check(n): if n < 0: - raise IndexError + raise MyError(n) return 5 def f(n): try: @@ -185,8 +186,9 @@ myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) n = n - check(n) - except IndexError: - return n + except MyError, e: + return e.n + assert f(53) == -2 res = self.meta_interp(f, [53], policy=StopAtXPolicy(check)) assert res == -2 From arigo at codespeak.net Thu Feb 12 18:14:19 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 18:14:19 +0100 (CET) Subject: [pypy-svn] r61802 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090212171419.42C1E169E51@codespeak.net> Author: arigo Date: Thu Feb 12 18:14:18 2009 New Revision: 61802 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: Fix bug. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Feb 12 18:14:18 2009 @@ -132,7 +132,7 @@ def repr_list(lst, types, cpu): res_l = [] - if types[-1] == 'varargs': + if types and types[-1] == 'varargs': types = types[:-1] + ('int',) * (len(lst) - len(types) + 1) assert len(types) == len(lst) for elem, tp in zip(lst, types): From jlg at codespeak.net Thu Feb 12 18:15:04 2009 From: jlg at codespeak.net (jlg at codespeak.net) Date: Thu, 12 Feb 2009 18:15:04 +0100 (CET) Subject: [pypy-svn] r61803 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090212171504.25ECD169E51@codespeak.net> Author: jlg Date: Thu Feb 12 18:15:03 2009 New Revision: 61803 Added: pypy/trunk/pypy/module/_locale/ pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/ pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (getxsick, jlg) started to rewrite of _locale to rffi Added: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/_locale/__init__.py Thu Feb 12 18:15:03 2009 @@ -0,0 +1,27 @@ +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + """Support for POSIX locales.""" + + interpleveldefs = { + #'Error': 'interp_locale.Error', + #'LocalConfigure': 'interp_locale.LocaleConfigure', + #'lconv': 'interp_locale.lconv', + #'fixup_ulcase': 'interp_locale.fixup_ulcase', + 'setlocale': 'interp_locale.setlocale', + 'localeconv': 'interp_locale.localeconv', + #'strcoll': 'interp_locale.strcoll', + #'strxfrm': 'interp_locale.strxfrm', + #'getdefaultlocale': 'interp_locale.getdefaultlocale', + #'gettext': 'interp_locale.gettext', + } + + appleveldefs = { + } + + def buildloaders(cls): + from pypy.module._locale import interp_locale + for constant, value in interp_locale.constants.iteritems(): + Module.interpleveldefs[constant] = "space.wrap(%r)" % value + super(Module, cls).buildloaders() + buildloaders = classmethod(buildloaders) Added: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Thu Feb 12 18:15:03 2009 @@ -0,0 +1,133 @@ +from pypy.rpython.tool import rffi_platform as platform +from pypy.rpython.lltypesystem import rffi, lltype + +from pypy.interpreter.gateway import interp2app, ObjSpace, W_Root + +from pypy.translator.tool.cbuild import ExternalCompilationInfo + +class CConfig: + _compilation_info_ = ExternalCompilationInfo( + includes = ['locale.h'] + ) + lconv = platform.Struct("struct lconv", [ + # Numeric (non-monetary) information. + ("decimal_point", rffi.CCHARP), # Decimal point character. + ("thousands_sep", rffi.CCHARP), # Thousands separator. + + ## Each element is the number of digits in each group; + ## elements with higher indices are farther left. + ## An element with value CHAR_MAX means that no further grouping is done. + ## An element with value 0 means that the previous element is used + ## for all groups farther left. */ + ("grouping", rffi.CCHARP), + + ## Monetary information. + + ## First three chars are a currency symbol from ISO 4217. + ## Fourth char is the separator. Fifth char is '\0'. + ("int_curr_symbol", rffi.CCHARP), + ("currency_symbol", rffi.CCHARP), # Local currency symbol. + ("mon_decimal_point", rffi.CCHARP), # Decimal point character. + ("mon_thousands_sep", rffi.CCHARP), # Thousands separator. + ("mon_grouping", rffi.CCHARP), # Like `grouping' element (above). + ("positive_sign", rffi.CCHARP), # Sign for positive values. + ("negative_sign", rffi.CCHARP), # Sign for negative values. + ("int_frac_digits", rffi.UCHAR), # Int'l fractional digits. + + ("frac_digits", rffi.CHAR), # Local fractional digits. + ## 1 if currency_symbol precedes a positive value, 0 if succeeds. + ("p_cs_precedes", rffi.CHAR), + ## 1 iff a space separates currency_symbol from a positive value. + ("p_sep_by_space", rffi.CHAR), + ## 1 if currency_symbol precedes a negative value, 0 if succeeds. + ("n_cs_precedes", rffi.CHAR), + ## 1 iff a space separates currency_symbol from a negative value. + ("n_sep_by_space", rffi.CHAR), + + ## Positive and negative sign positions: + ## 0 Parentheses surround the quantity and currency_symbol. + ## 1 The sign string precedes the quantity and currency_symbol. + ## 2 The sign string follows the quantity and currency_symbol. + ## 3 The sign string immediately precedes the currency_symbol. + ## 4 The sign string immediately follows the currency_symbol. + ("p_sign_posn", rffi.CHAR), + ("n_sign_posn", rffi.CHAR), + ]) + + +constants = {} +constant_names = ( + 'LC_CTYPE', + 'LC_NUMERIC', + 'LC_TIME', + 'LC_COLLATE', + 'LC_MONETARY', + 'LC_MESSAGES', + 'LC_ALL', + 'LC_PAPER', + 'LC_NAME', + 'LC_ADDRESS', + 'LC_TELEPHONE', + 'LC_MEASUREMENT', + 'LC_IDENTIFICATION', + ) + +for name in constant_names: + setattr(CConfig, name, platform.DefinedConstantInteger(name)) + +class cConfig(object): + pass + +for k, v in platform.configure(CConfig).items(): + setattr(cConfig, k, v) + +# needed to export the constants inside and outside. see __init__.py +for name in constant_names: + value = getattr(cConfig, name) + if value is not None: + constants[name] = value + +locals().update(constants) + +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=CConfig._compilation_info_) + +def setlocale(space, w_category, w_locale): + pass + +setlocale.unwrap_spec = [ObjSpace, W_Root, W_Root] + +_lconv = lltype.Ptr(cConfig.lconv) +_localeconv = external('localeconv', [], _lconv) + +def localeconv(space): + lp = _localeconv() + + # hopefully, the localeconv result survives the C library calls + # involved herein + + # Numeric information + result = { + "decimal_point": rffi.charp2str(lp.c_decimal_point), + #"thousands_sep": rffi.getintfield(lp, "c_thousands_sep"), + #"grouping": rffi.getintfield(lp, "c_grouping"), #_copy_grouping(l.grouping)), + #"int_curr_symbol": rffi.getintfield(lp, "c_int_curr_symbol"), + #"currency_symbol": rffi.getintfield(lp, "c_currency_symbol"), + #"mon_decimal_point": rffi.getintfield(lp, "c_mon_decimal_point"), + #"mon_thousands_sep": rffi.getintfield(lp, "c_mon_thousands_sep"), + #"mon_grouping": rffi.getintfield(lp, "c_mon_grouping"), #_copy_grouping(l.mon_grouping)), + #"positive_sign": rffi.getintfield(lp, "c_positive_sign"), + #"negative_sign": rffi.getintfield(lp, "c_negative_sign"), + #"int_frac_digits": rffi.getintfield(lp, "c_int_frac_digits"), + #"frac_digits": rffi.getintfield(lp, "c_frac_digits"), + #"p_cs_precedes": rffi.getintfield(lp, "c_p_cs_precedes"), + #"p_sep_by_space": rffi.getintfield(lp, "c_p_sep_by_space"), + #"n_cs_precedes": rffi.getintfield(lp, "c_n_cs_precedes"), + #"n_sep_by_space": rffi.getintfield(lp, "c_n_sep_by_space"), + #"p_sign_posn": rffi.getintfield(lp, "c_p_sign_posn"), + #"n_sign_posn": rffi.getintfield(lp, "c_n_sign_posn"), + } + return space.wrap(result) + +localeconv.unwrap_spec = [ObjSpace] + Added: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Thu Feb 12 18:15:03 2009 @@ -0,0 +1,50 @@ +from pypy.conftest import gettestobjspace + +import sys + +class AppTestLocaleTrivia: + def setup_class(cls): + cls.space = gettestobjspace(usemodules=['_locale']) + + #cls.w_locale = cls.space.appexec([], """(): + # import locale + # return locale""") + + def test_import(self): + import _locale + assert _locale + + import locale + assert locale + + def test_contants(self): + _CONSTANTS = ( + 'LC_CTYPE', + 'LC_NUMERIC', + 'LC_TIME', + 'LC_COLLATE', + 'LC_MONETARY', + 'LC_MESSAGES', + 'LC_ALL', + 'LC_PAPER', + 'LC_NAME', + 'LC_ADDRESS', + 'LC_TELEPHONE', + 'LC_MEASUREMENT', + 'LC_IDENTIFICATION', + ) + + import _locale + + for constant in _CONSTANTS: + assert hasattr(_locale, constant) + + def test_str_float(self): + skip("in progress") + import locale + + locale.setlocale(locale.LC_ALL, "en_US") + assert locale.str(1.1) == '1.1' + locale.setlocale(locale.LC_ALL, "pl_PL") + assert locale.str(1.1) == '1,1' + From arigo at codespeak.net Thu Feb 12 18:46:10 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 18:46:10 +0100 (CET) Subject: [pypy-svn] r61806 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090212174610.1BAF6169E1C@codespeak.net> Author: arigo Date: Thu Feb 12 18:46:09 2009 New Revision: 61806 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: (fijal, arigo) Waaa. Bouh. That took us quite some time to find. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Thu Feb 12 18:46:09 2009 @@ -86,13 +86,14 @@ self.setfields = [] def deal_with_box(self, box, nodes, liveboxes, memo): - if box in memo: - return memo[box] if isinstance(box, Const): virtual = False virtualized = False else: instnode = nodes[box] + box = instnode.source + if box in memo: + return memo[box] virtual = instnode.virtual virtualized = instnode.virtualized if virtual: From arigo at codespeak.net Thu Feb 12 18:46:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 12 Feb 2009 18:46:44 +0100 (CET) Subject: [pypy-svn] r61807 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090212174644.69EAA169E9D@codespeak.net> Author: arigo Date: Thu Feb 12 18:46:44 2009 New Revision: 61807 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: A new test (that passes). Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Thu Feb 12 18:46:44 2009 @@ -154,3 +154,39 @@ assert len(spec.specnodes[0].fields) == 1 assert spec.specnodes[0].fields[0][0] == B.ofs_node assert spec.specnodes[0].fields[0][1] is None + +# ____________________________________________________________ + +class C: + locals().update(B.__dict__) + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + v2 = BoxInt(13) + ops = [ + MergePoint('merge_point', [fr], []), + ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), + ConstInt(ofs_node)], []), + # + ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n1]), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + # + ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n2]), + ResOperation('guard_class', [n2, ConstAddr(node_vtable, cpu)], []), + ResOperation('getfield_gc', [n2, ConstInt(ofs_value)], [v2]), + # + Jump('jump', [fr], []), + ] + ops[1].vdesc = xy_desc + +def test_C_intersect_input_and_output(): + spec = PerfectSpecializer(C.ops) + spec.find_nodes() + spec.intersect_input_and_output() + assert spec.nodes[C.fr].escaped + assert spec.nodes[C.fr].virtualized + assert not spec.nodes[C.n1].escaped + assert not spec.nodes[C.n2].escaped + assert isinstance(spec.specnodes[0], VirtualizableSpecNode) + assert len(spec.specnodes[0].fields) == 1 + assert spec.specnodes[0].fields[0][0] == C.ofs_node + assert spec.specnodes[0].fields[0][1] is None From fijal at codespeak.net Thu Feb 12 18:57:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 12 Feb 2009 18:57:09 +0100 (CET) Subject: [pypy-svn] r61809 - in pypy/branch/pyjitpl5/pypy/jit: metainterp metainterp/test tl Message-ID: <20090212175709.EAEB8169E1B@codespeak.net> Author: fijal Date: Thu Feb 12 18:57:08 2009 New Revision: 61809 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Log: (arigo, fijal) Reintroduction of promoting hint. Next thing is to have virtual lists and we'll have a nice and fast tl :) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Feb 12 18:57:08 2009 @@ -387,14 +387,14 @@ serialize_op_unichar_eq = serialize_op_char_eq serialize_op_unichar_ne = serialize_op_char_ne -## def serialize_op_hint(self, op): -## hints = op.args[1].value -## if hints.get('promote') and op.args[0].concretetype is not lltype.Void: -## self.minimize_variables() -## self.emit('guard_value', self.var_position(op.args[0])) -## self.register_var(op.result) -## else: -## self.serialize_op_same_as(op) + def serialize_op_hint(self, op): + hints = op.args[1].value + if hints.get('promote') and op.args[0].concretetype is not lltype.Void: + self.minimize_variables() + self.emit('guard_value', self.var_position(op.args[0])) + self.register_var(op.result) + else: + xxx def serialize_op_int_is_true(self, op): if isinstance(op.args[0], Constant): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 12 18:57:08 2009 @@ -402,7 +402,7 @@ @arguments("orgpc", "box", returns="box") def opimpl_guard_value(self, pc, box): - self.implement_guard_value(pc, box) + return self.implement_guard_value(pc, box) @arguments("orgpc", "box", returns="box") def opimpl_guard_class(self, pc, box): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Thu Feb 12 18:57:08 2009 @@ -37,7 +37,7 @@ self.check_loops({'merge_point': 1, 'jump': 1, 'int_gt': 1, 'guard_true': 1, 'int_sub': 1}) - + def test_loop(self): myjitdriver = JitDriver(greens = [], reds = ['n']) def check(n): Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tl.py Thu Feb 12 18:57:08 2009 @@ -2,7 +2,7 @@ import py from pypy.jit.tl.tlopcode import * -from pypy.rlib.jit import JitDriver +from pypy.rlib.jit import JitDriver, hint def char2int(c): t = ord(c) @@ -66,6 +66,7 @@ myjitdriver.jit_merge_point(pc=pc, code=code, stack=stack, inputarg=inputarg) opcode = ord(code[pc]) + stack.stackpos = hint(stack.stackpos, promote=True) pc += 1 if opcode == NOP: From antocuni at codespeak.net Thu Feb 12 21:02:53 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 12 Feb 2009 21:02:53 +0100 (CET) Subject: [pypy-svn] r61811 - pypy/branch/oo-jit/pypy/jit/codegen/cli/test Message-ID: <20090212200253.543A5169E99@codespeak.net> Author: antocuni Date: Thu Feb 12 21:02:50 2009 New Revision: 61811 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Log: explain why these two tests fail Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Thu Feb 12 21:02:50 2009 @@ -28,10 +28,10 @@ py.test.skip('fixme') def test_float_adder(self): - py.test.skip('fixme') + py.test.skip('Pythonnet bug: il.Emit(..., 3.2) selects the wrong overload') def test_float_loop_direct(self): - py.test.skip('fixme') + py.test.skip('Pythonnet bug: il.Emit(..., 3.2) selects the wrong overload') def test_read_frame_var_direct(self): py.test.skip('fixme: add support for frames') From afa at codespeak.net Fri Feb 13 01:25:27 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Feb 2009 01:25:27 +0100 (CET) Subject: [pypy-svn] r61815 - pypy/trunk/pypy/lib/_ctypes Message-ID: <20090213002527.AEA9716855F@codespeak.net> Author: afa Date: Fri Feb 13 01:25:26 2009 New Revision: 61815 Modified: pypy/trunk/pypy/lib/_ctypes/union.py Log: Remove unneeded import Modified: pypy/trunk/pypy/lib/_ctypes/union.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/union.py (original) +++ pypy/trunk/pypy/lib/_ctypes/union.py Fri Feb 13 01:25:26 2009 @@ -5,7 +5,6 @@ from _ctypes.basics import ensure_objects from _ctypes.structure import round_up, names_and_fields, struct_getattr,\ struct_setattr -import inspect def _set_shape(tp): From afa at codespeak.net Fri Feb 13 01:33:33 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Feb 2009 01:33:33 +0100 (CET) Subject: [pypy-svn] r61816 - in pypy/trunk/pypy: lib/_ctypes module/_rawffi Message-ID: <20090213003333.55585169E15@codespeak.net> Author: afa Date: Fri Feb 13 01:33:31 2009 New Revision: 61816 Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Log: Add support for the "X" primitive type: BSTR which is a unicode string managed by the Windows API. Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/primitive.py (original) +++ pypy/trunk/pypy/lib/_ctypes/primitive.py Fri Feb 13 01:33:31 2009 @@ -211,6 +211,34 @@ return pyobj_container.get(self._buffer[0]) result.value = property(_getvalue, _setvalue) + elif tp == 'X': + from ctypes import windll + SysAllocStringLen = windll.oleaut32.SysAllocStringLen + SysStringLen = windll.oleaut32.SysStringLen + SysFreeString = windll.oleaut32.SysFreeString + from _ctypes import _wstring_at_addr + def _getvalue(self): + addr = self._buffer[0] + if addr == 0: + return None + else: + size = SysStringLen(addr) + return _wstring_at_addr(addr, size) + + def _setvalue(self, value): + if isinstance(value, basestring): + if isinstance(value, str): + value = value.decode(ConvMode.encoding, + ConvMode.errors) + array = _rawffi.Array('u')(len(value)+1, value) + value = SysAllocStringLen(array.buffer, len(value)) + elif value is None: + value = 0 + if self._buffer[0]: + SysFreeString(self._buffer[0]) + self._buffer[0] = value + result.value = property(_getvalue, _setvalue) + return result from_address = cdata_from_address Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Fri Feb 13 01:33:31 2009 @@ -75,6 +75,9 @@ 'P' : rffi.VOIDP, } +if _MS_WINDOWS: + LL_TYPEMAP['X'] = rffi.CCHARP + def letter2tp(space, key): try: return UNPACKED_TYPECODES[key] From afa at codespeak.net Fri Feb 13 10:38:17 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Feb 2009 10:38:17 +0100 (CET) Subject: [pypy-svn] r61817 - pypy/trunk/pypy/rlib Message-ID: <20090213093817.43C0E169DB7@codespeak.net> Author: afa Date: Fri Feb 13 10:38:15 2009 New Revision: 61817 Modified: pypy/trunk/pypy/rlib/libffi.py Log: Hopefully fix translation on Unix, where this exception is caught but never raised. Modified: pypy/trunk/pypy/rlib/libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/libffi.py (original) +++ pypy/trunk/pypy/rlib/libffi.py Fri Feb 13 10:38:15 2009 @@ -391,6 +391,7 @@ userdata.callback(ll_args, ll_res, userdata) class StackCheckError(ValueError): + message = None def __init__(self, message): self.message = message From fijal at codespeak.net Fri Feb 13 12:44:01 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 12:44:01 +0100 (CET) Subject: [pypy-svn] r61821 - pypy/branch/js-refactoring-quickhacks Message-ID: <20090213114401.24EB816854A@codespeak.net> Author: fijal Date: Fri Feb 13 12:43:58 2009 New Revision: 61821 Removed: pypy/branch/js-refactoring-quickhacks/ Log: I don't want to even look what quickhacks are there From fijal at codespeak.net Fri Feb 13 12:44:16 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 12:44:16 +0100 (CET) Subject: [pypy-svn] r61822 - pypy/branch/js-refactoring Message-ID: <20090213114416.2A3A1168556@codespeak.net> Author: fijal Date: Fri Feb 13 12:44:15 2009 New Revision: 61822 Removed: pypy/branch/js-refactoring/ Log: This one also is at least completely outdated From fijal at codespeak.net Fri Feb 13 13:28:53 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 13:28:53 +0100 (CET) Subject: [pypy-svn] r61825 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090213122853.3864D16857A@codespeak.net> Author: fijal Date: Fri Feb 13 13:28:52 2009 New Revision: 61825 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: kill hint Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Fri Feb 13 13:28:52 2009 @@ -1,5 +1,5 @@ import py -from pypy.rlib.jit import JitDriver, hint +from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp import support, codewriter, pyjitpl, history @@ -86,7 +86,6 @@ def test_basic_mp(self): def f(x, y): - hint(x, concrete=True) return x + y res = self.interp_operations(f, [40, 2]) assert res == 42 From fijal at codespeak.net Fri Feb 13 13:54:25 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 13:54:25 +0100 (CET) Subject: [pypy-svn] r61826 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090213125425.071D8169E25@codespeak.net> Author: fijal Date: Fri Feb 13 13:54:23 2009 New Revision: 61826 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: Fix tests Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Fri Feb 13 13:54:23 2009 @@ -72,7 +72,7 @@ res = self.meta_interp(f, [1], policy=StopAtXPolicy(externfn), backendopt=True) assert res == 43 - self.check_loops({'call_ptr': 1, 'guard_exception': 1, + self.check_loops({'call_ptr': 1, 'guard_no_exception': 1, 'getfield_gc': 1, 'int_add': 1, 'merge_point' : 1, 'jump': 1, 'int_gt' : 1, 'guard_true' : 1, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Fri Feb 13 13:54:23 2009 @@ -17,7 +17,6 @@ myjitdriver.can_enter_jit(y=y, pc=pc, acc=acc, s=s) myjitdriver.jit_merge_point(y=y, pc=pc, acc=acc, s=s) op = s[pc] - hint(op, concrete=True) if op == '+': acc += y elif op == '-': @@ -27,7 +26,7 @@ codes = ["++++++++++", "+-++---+-++-"] def main(n, x, y): - code = hint(codes, deepfreeze=True)[n] + code = codes[n] return ll_plus_minus(code, x, y) res = self.meta_interp(main, [0, 100, 2]) From fijal at codespeak.net Fri Feb 13 13:57:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 13:57:48 +0100 (CET) Subject: [pypy-svn] r61827 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213125748.24E66169E25@codespeak.net> Author: fijal Date: Fri Feb 13 13:57:47 2009 New Revision: 61827 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py Log: Refactor pieces from optimize into specnode.py. Now it's all nicely handled by oo-style calls instead of isintance checks a bit everywhere Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 13:57:47 2009 @@ -1,75 +1,14 @@ from pypy.jit.metainterp.history import (Box, Const, ConstInt, MergePoint, ResOperation, Jump) from pypy.jit.metainterp.heaptracker import always_pure_operations +from pypy.jit.metainterp.specnode import (FixedClassSpecNode, + VirtualInstanceSpecNode, + VirtualizableSpecNode, + NotSpecNode) class CancelInefficientLoop(Exception): pass -class FixedClassSpecNode(object): - def __init__(self, known_class): - self.known_class = known_class - - def equals(self, other): - if type(other) is not FixedClassSpecNode: - return False - else: - assert isinstance(other, FixedClassSpecNode) # make annotator happy - return self.known_class.equals(other.known_class) - - def matches(self, instnode): - if instnode.cls is None: - return False - return instnode.cls.source.equals(self.known_class) - -class SpecNodeWithFields(FixedClassSpecNode): - def __init__(self, known_class, fields): - FixedClassSpecNode.__init__(self, known_class) - self.fields = fields - - def equals(self, other): - if not self.known_class.equals(other.known_class): - return False - elif len(self.fields) != len(other.fields): - return False - else: - for i in range(len(self.fields)): - key, value = self.fields[i] - otherkey, othervalue = other.fields[i] - if key != otherkey: - return False - if value is None: - if othervalue is not None: - return False - else: - if not value.equals(othervalue): - return False - return True - - def matches(self, instnode): - # XXX think about details of virtual vs virtualizable - if not FixedClassSpecNode.matches(self, instnode): - return False - for key, value in self.fields: - if key not in instnode.curfields: - return False - if value is not None and not value.matches(instnode.curfields[key]): - return False - return True - -class VirtualizableSpecNode(SpecNodeWithFields): - - def equals(self, other): - if not isinstance(other, VirtualizableSpecNode): - return False - return SpecNodeWithFields.equals(self, other) - -class VirtualInstanceSpecNode(SpecNodeWithFields): - - def equals(self, other): - if not isinstance(other, VirtualInstanceSpecNode): - return False - return SpecNodeWithFields.equals(self, other) - class AllocationStorage(object): def __init__(self): # allocations: list of vtables to allocate @@ -122,19 +61,6 @@ type_cache = TypeCache() # XXX remove me later type_cache.class_size = {} -def extract_runtime_data(cpu, specnode, valuebox, resultlist): - if not isinstance(specnode, VirtualInstanceSpecNode): - resultlist.append(valuebox) - if isinstance(specnode, SpecNodeWithFields): - for ofs, subspecnode in specnode.fields: - cls = specnode.known_class.getint() - tp = cpu.typefor(ofs) - fieldbox = cpu.execute_operation('getfield_gc', - [valuebox, ConstInt(ofs)], - tp) - extract_runtime_data(cpu, subspecnode, fieldbox, resultlist) - - class InstanceNode(object): def __init__(self, source, escaped=True, startbox=False, const=False): self.source = source # a Box @@ -164,7 +90,7 @@ def intersect(self, other): if not other.cls: - return None + return NotSpecNode() if self.cls: if not self.cls.source.equals(other.cls.source): raise CancelInefficientLoop @@ -173,7 +99,7 @@ known_class = other.cls.source if other.escaped and not other.virtualized: if self.cls is None: - return None + return NotSpecNode() return FixedClassSpecNode(known_class) if not other.escaped: fields = [] @@ -184,7 +110,7 @@ specnode = self.origfields[ofs].intersect(node) else: self.origfields[ofs] = InstanceNode(node.source.clonebox()) - specnode = None + specnode = NotSpecNode() fields.append((ofs, specnode)) return VirtualInstanceSpecNode(known_class, fields) else: @@ -199,23 +125,16 @@ node = other.curfields[ofs] specnode = self.origfields[ofs].intersect(node) elif ofs in self.origfields: - specnode = None + specnode = NotSpecNode() else: # ofs in other.curfields node = other.curfields[ofs] self.origfields[ofs] = InstanceNode(node.source.clonebox()) - specnode = None + specnode = NotSpecNode() fields.append((ofs, specnode)) return VirtualizableSpecNode(known_class, fields) - def adapt_to(self, specnode): - if not isinstance(specnode, VirtualInstanceSpecNode): - self.escaped = True - return - for ofs, subspecnode in specnode.fields: - self.curfields[ofs].adapt_to(subspecnode) - def __repr__(self): flags = '' if self.escaped: flags += 'e' @@ -365,41 +284,15 @@ specnodes.append(enternode.intersect(leavenode)) self.specnodes = specnodes - def mutate_nodes(self, instnode, specnode): - if specnode is not None: - if instnode.cls is None: - instnode.cls = InstanceNode(specnode.known_class) - else: - assert instnode.cls.source.equals(specnode.known_class) - if isinstance(specnode, SpecNodeWithFields): - curfields = {} - for ofs, subspecnode in specnode.fields: - subinstnode = instnode.origfields[ofs] - # should really be there - self.mutate_nodes(subinstnode, subspecnode) - curfields[ofs] = subinstnode - instnode.curfields = curfields - if isinstance(specnode, VirtualInstanceSpecNode): - instnode.virtual = True - def expanded_version_of(self, boxlist): newboxlist = [] assert len(boxlist) == len(self.specnodes) for i in range(len(boxlist)): box = boxlist[i] specnode = self.specnodes[i] - self.expanded_version_of_rec(specnode, self.nodes[box], newboxlist) + specnode.expand_boxlist(self.nodes[box], newboxlist) return newboxlist - def expanded_version_of_rec(self, specnode, instnode, newboxlist): - if not isinstance(specnode, VirtualInstanceSpecNode): - newboxlist.append(instnode.source) - if isinstance(specnode, SpecNodeWithFields): - for ofs, subspecnode in specnode.fields: - subinstnode = instnode.curfields[ofs] # should really be there - self.expanded_version_of_rec(subspecnode, subinstnode, - newboxlist) - def optimize_guard(self, op): liveboxes = [] storage = AllocationStorage() @@ -437,7 +330,7 @@ assert len(self.operations[0].args) == len(self.specnodes) for i in range(len(self.specnodes)): box = self.operations[0].args[i] - self.mutate_nodes(self.nodes[box], self.specnodes[i]) + self.specnodes[i].mutate_nodes(self.nodes[box]) else: assert self.operations[0].opname == 'catch' for box in self.operations[0].args: @@ -544,12 +437,8 @@ for i in range(len(self.specnodes)): old_specnode = old_mp.specnodes[i] new_specnode = self.specnodes[i] - if old_specnode is None: - if new_specnode is not None: - return False - else: - if not old_specnode.equals(new_specnode): - return False + if not old_specnode.equals(new_specnode): + return False return True def match(self, old_operations): @@ -560,9 +449,8 @@ for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] new_instnode = self.nodes[jump_op.args[i]] - if old_specnode is not None: - if not old_specnode.matches(new_instnode): - return False + if not old_specnode.matches(new_instnode): + return False return True def adapt_for_match(self, old_operations): @@ -572,7 +460,7 @@ for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] new_instnode = self.nodes[jump_op.args[i]] - new_instnode.adapt_to(old_specnode) + old_specnode.adapt_to(new_instnode) def rebuild_boxes_from_guard_failure(guard_op, history, boxes_from_frame): allocated_boxes = [] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Feb 13 13:57:47 2009 @@ -762,8 +762,7 @@ expanded_args = [] for i in range(len(mp.specnodes)): specnode = mp.specnodes[i] - optimize.extract_runtime_data(self.cpu, specnode, - args[i], expanded_args) + specnode.extract_runtime_data(self.cpu, args[i], expanded_args) return expanded_args def initialize_state_from_start(self, args): Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Fri Feb 13 13:57:47 2009 @@ -0,0 +1,140 @@ + +from pypy.jit.metainterp.history import ConstInt + +class SpecNode(object): + + def expand_boxlist(self, instnode, newboxlist): + newboxlist.append(instnode.source) + + def extract_runtime_data(self, cpu, valuebox, resultlist): + resultlist.append(valuebox) + + def adapt_to(self, instnode): + instnode.escaped = True + +class NotSpecNode(SpecNode): + def mutate_nodes(self, instnode): + pass + + def equals(self, other): + if type(other) is NotSpecNode: + return True + return False + + def matches(self, other): + # NotSpecNode matches everything + return True + +class FixedClassSpecNode(SpecNode): + def __init__(self, known_class): + self.known_class = known_class + + def mutate_nodes(self, instnode): + from pypy.jit.metainterp.optimize import InstanceNode + + if instnode.cls is None: + instnode.cls = InstanceNode(self.known_class) + else: + assert instnode.cls.source.equals(self.known_class) + + def equals(self, other): + if type(other) is not FixedClassSpecNode: + return False + else: + assert isinstance(other, FixedClassSpecNode) # make annotator happy + return self.known_class.equals(other.known_class) + + def matches(self, instnode): + if instnode.cls is None: + return False + return instnode.cls.source.equals(self.known_class) + +class SpecNodeWithFields(FixedClassSpecNode): + def __init__(self, known_class, fields): + FixedClassSpecNode.__init__(self, known_class) + self.fields = fields + + def mutate_nodes(self, instnode): + FixedClassSpecNode.mutate_nodes(self, instnode) + curfields = {} + for ofs, subspecnode in self.fields: + subinstnode = instnode.origfields[ofs] + # should really be there + subspecnode.mutate_nodes(subinstnode) + curfields[ofs] = subinstnode + instnode.curfields = curfields + + def equals(self, other): + if not self.known_class.equals(other.known_class): + return False + elif len(self.fields) != len(other.fields): + return False + else: + for i in range(len(self.fields)): + key, value = self.fields[i] + otherkey, othervalue = other.fields[i] + if key != otherkey: + return False + if not value.equals(othervalue): + return False + return True + + def matches(self, instnode): + # XXX think about details of virtual vs virtualizable + if not FixedClassSpecNode.matches(self, instnode): + return False + for key, value in self.fields: + if key not in instnode.curfields: + return False + if value is not None and not value.matches(instnode.curfields[key]): + return False + return True + + def expand_boxlist(self, instnode, newboxlist): + for ofs, subspecnode in self.fields: + subinstnode = instnode.curfields[ofs] # should really be there + subspecnode.expand_boxlist(subinstnode, newboxlist) + + def extract_runtime_data(self, cpu, valuebox, resultlist): + for ofs, subspecnode in self.fields: + cls = self.known_class.getint() + tp = cpu.typefor(ofs) + fieldbox = cpu.execute_operation('getfield_gc', + [valuebox, ConstInt(ofs)], + tp) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + + def adapt_to(self, instnode): + for ofs, subspecnode in self.fields: + subspecnode.adapt_to(instnode.curfields[ofs]) + +class VirtualizableSpecNode(SpecNodeWithFields): + + def equals(self, other): + if not isinstance(other, VirtualizableSpecNode): + return False + return SpecNodeWithFields.equals(self, other) + + def expand_boxlist(self, instnode, newboxlist): + newboxlist.append(instnode.source) + SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist) + + def extract_runtime_data(self, cpu, valuebox, resultlist): + resultlist.append(valuebox) + SpecNodeWithFields.extract_runtime_data(self, cpu, valuebox, resultlist) + + def adapt_to(self, instnode): + instnode.escaped = True + SpecNodeWithFields.adapt_to(self, instnode) + +class VirtualInstanceSpecNode(SpecNodeWithFields): + + def mutate_nodes(self, instnode): + SpecNodeWithFields.mutate_nodes(self, instnode) + instnode.virtual = True + + def equals(self, other): + if not isinstance(other, VirtualInstanceSpecNode): + return False + return SpecNodeWithFields.equals(self, other) + Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 13:57:47 2009 @@ -10,7 +10,8 @@ Jump, GuardOp) from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, - rebuild_boxes_from_guard_failure, type_cache, AllocationStorage) + rebuild_boxes_from_guard_failure, type_cache, AllocationStorage, + NotSpecNode) cpu = runner.CPU(None) @@ -109,10 +110,11 @@ spec.intersect_input_and_output() assert len(spec.specnodes) == 2 spec_sum, spec_n = spec.specnodes - assert spec_sum is None # for now + assert isinstance(spec_sum, NotSpecNode) assert isinstance(spec_n, VirtualInstanceSpecNode) assert spec_n.known_class.value == node_vtable_adr - assert spec_n.fields == [(A.ofs_value, None)] + assert spec_n.fields[0][0] == A.ofs_value + assert isinstance(spec_n.fields[0][1], NotSpecNode) def test_A_optimize_loop(): operations = A.ops[:] @@ -158,7 +160,7 @@ spec.intersect_input_and_output() assert len(spec.specnodes) == 2 spec_sum, spec_n = spec.specnodes - assert spec_sum is None # for now + assert isinstance(spec_sum, NotSpecNode) assert type(spec_n) is FixedClassSpecNode assert spec_n.known_class.value == node_vtable_adr @@ -213,7 +215,7 @@ assert spec.nodes[C.n2].escaped assert len(spec.specnodes) == 2 spec_sum, spec_n = spec.specnodes - assert spec_sum is None # for now + assert isinstance(spec_sum, NotSpecNode) assert type(spec_n) is FixedClassSpecNode assert spec_n.known_class.value == node_vtable_adr Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Fri Feb 13 13:57:47 2009 @@ -7,7 +7,8 @@ ConstInt, ConstAddr, BoxInt, BoxPtr) from pypy.jit.metainterp.optimize import (PerfectSpecializer, VirtualizableSpecNode, - VirtualInstanceSpecNode) + VirtualInstanceSpecNode, + NotSpecNode) from pypy.jit.metainterp.virtualizable import VirtualizableDesc from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, equaloplists) @@ -153,7 +154,7 @@ assert isinstance(spec.specnodes[0], VirtualizableSpecNode) assert len(spec.specnodes[0].fields) == 1 assert spec.specnodes[0].fields[0][0] == B.ofs_node - assert spec.specnodes[0].fields[0][1] is None + assert isinstance(spec.specnodes[0].fields[0][1], NotSpecNode) # ____________________________________________________________ @@ -189,4 +190,4 @@ assert isinstance(spec.specnodes[0], VirtualizableSpecNode) assert len(spec.specnodes[0].fields) == 1 assert spec.specnodes[0].fields[0][0] == C.ofs_node - assert spec.specnodes[0].fields[0][1] is None + assert isinstance(spec.specnodes[0].fields[0][1], NotSpecNode) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py Fri Feb 13 13:57:47 2009 @@ -1,5 +1,5 @@ from pypy.jit.metainterp.warmspot import ll_meta_interp -from pypy.rlib.jit import hint, JitDriver +from pypy.rlib.jit import JitDriver class Exit(Exception): def __init__(self, result): @@ -20,11 +20,9 @@ i = 0 while True: mydriver.jit_merge_point(i=i, a=a) - lst2 = hint(lst, deepfreeze=True) - if i >= len(lst2): + if i >= len(lst): break - elem = lst2[i] - hint(elem, concrete=True) + elem = lst[i] if elem == CODE_INCREASE: a = a + 1 i += 1 From afa at codespeak.net Fri Feb 13 14:01:18 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Feb 2009 14:01:18 +0100 (CET) Subject: [pypy-svn] r61828 - pypy/trunk/pypy/lib/_ctypes Message-ID: <20090213130118.35E54169E2B@codespeak.net> Author: afa Date: Fri Feb 13 14:01:15 2009 New Revision: 61828 Modified: pypy/trunk/pypy/lib/_ctypes/function.py Log: Avoid a segfault in error conditions Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Fri Feb 13 14:01:15 2009 @@ -172,6 +172,8 @@ if self._com_index: # extract the address from the object's virtual table + if not thisarg: + raise ValueError("COM method call without VTable") ptr = thisarg[self._com_index - 0x1000] return _rawffi.FuncPtr(ptr, argshapes, resshape, self._flags_) From afa at codespeak.net Fri Feb 13 15:33:25 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Feb 2009 15:33:25 +0100 (CET) Subject: [pypy-svn] r61832 - in pypy/trunk/pypy: lib/_ctypes lib/app_test/ctypes_tests module/_rawffi Message-ID: <20090213143325.52042169E3A@codespeak.net> Author: afa Date: Fri Feb 13 15:33:24 2009 New Revision: 61832 Modified: pypy/trunk/pypy/lib/_ctypes/function.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_funcptr.py pypy/trunk/pypy/module/_rawffi/callback.py Log: Callbacks also should honor the flags=FUNCFLAG_STDCALL attribute Test and fix. Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Fri Feb 13 15:33:24 2009 @@ -85,7 +85,7 @@ ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._ptr = _rawffi.CallbackPtr(self._wrap_callable(argument, self.argtypes), - ffiargs, ffires) + ffiargs, ffires, self._flags_) self._buffer = self._ptr.byptr() elif isinstance(argument, tuple) and len(argument) == 2: # function exported from a shared library @@ -252,7 +252,7 @@ except (UnicodeError, TypeError), e: raise ArgumentError(str(e)) wrapped_args.append(wrapped) - argtypes.extend(extra_types) + argtypes = list(argtypes) + extra_types return argtypes, wrapped_args def _build_result(self, restype, resbuffer, argtypes, argsandobjs): Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_funcptr.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_funcptr.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_funcptr.py Fri Feb 13 15:33:24 2009 @@ -1,5 +1,5 @@ import py -import os, unittest +import sys, os, unittest from ctypes import * try: @@ -48,7 +48,8 @@ raises(TypeError, s, 1, 2, 3) def test_structures(self): - py.test.skip("win32 related") + if sys.platform != 'win32': + py.test.skip("win32 related") WNDPROC = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int) def wndproc(hwnd, msg, wParam, lParam): Modified: pypy/trunk/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/callback.py (original) +++ pypy/trunk/pypy/module/_rawffi/callback.py Fri Feb 13 15:33:24 2009 @@ -8,7 +8,7 @@ from pypy.module._rawffi.array import get_elem, push_elem from pypy.module._rawffi.interp_rawffi import W_DataInstance, _get_type_,\ wrap_value, unwrap_value, unwrap_truncate_int, letter2tp -from pypy.rlib.libffi import USERDATA_P, CallbackFuncPtr +from pypy.rlib.libffi import USERDATA_P, CallbackFuncPtr, FUNCFLAG_CDECL from pypy.module._rawffi.tracker import tracker from pypy.interpreter.error import OperationError from pypy.interpreter import gateway @@ -52,7 +52,8 @@ class W_CallbackPtr(W_DataInstance): global_counter = global_counter - def __init__(self, space, w_callable, w_args, w_result): + def __init__(self, space, w_callable, w_args, w_result, + flags=FUNCFLAG_CDECL): number = global_counter.CallbackPtr_id global_counter.CallbackPtr_id += 1 global_counter.CallbackPtr_by_number[number] = self @@ -66,7 +67,7 @@ ffiresult = _get_type_(space, self.result) # necessary to keep stuff alive self.ll_callback = CallbackFuncPtr(ffiargs, ffiresult, - callback, number) + callback, number, flags) self.ll_buffer = rffi.cast(rffi.VOIDP, self.ll_callback.ll_closure) if tracker.DO_TRACING: addr = rffi.cast(lltype.Signed, self.ll_callback.ll_closure) @@ -79,8 +80,11 @@ del self.global_counter.CallbackPtr_by_number[self.number] free.unwrap_spec = ['self'] -def descr_new_callbackptr(space, w_type, w_callable, w_args, w_result): - return W_CallbackPtr(space, w_callable, w_args, w_result) +def descr_new_callbackptr(space, w_type, w_callable, w_args, w_result, + flags=FUNCFLAG_CDECL): + return W_CallbackPtr(space, w_callable, w_args, w_result, flags) +descr_new_callbackptr.unwrap_spec = [ObjSpace, W_Root, W_Root, W_Root, W_Root, + int] W_CallbackPtr.typedef = TypeDef( 'CallbackPtr', From fijal at codespeak.net Fri Feb 13 16:08:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 16:08:29 +0100 (CET) Subject: [pypy-svn] r61833 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213150829.4233E169E1F@codespeak.net> Author: fijal Date: Fri Feb 13 16:08:27 2009 New Revision: 61833 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: Pass loop instead of operations into optimize.py Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Feb 13 16:08:27 2009 @@ -5,7 +5,7 @@ from pypy.rlib import objectmodel from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.history import Const, getkind, getkind_num -from pypy.jit.metainterp import heaptracker, support, history, optimize +from pypy.jit.metainterp import heaptracker, support, history import py from pypy.tool.ansi_print import ansi_log Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Fri Feb 13 16:08:27 2009 @@ -117,7 +117,7 @@ history = metainterp.history loop.operations = history.operations close_loop(loop, loop.operations[0], endliveboxes) - old_loop = optimize.optimize_loop(metainterp, old_loops, loop.operations) + old_loop = optimize.optimize_loop(metainterp, old_loops, loop) if old_loop is not None: return old_loop finish_loop_or_bridge(metainterp, loop, loop.operations[0]) @@ -153,7 +153,7 @@ op = Jump('jump', endliveboxes, []) operations.append(op) # - old_loop = optimize.optimize_bridge(metainterp, old_loops, operations) + old_loop = optimize.optimize_bridge(metainterp, old_loops, bridge) if old_loop is None: return None bridge.jump_to = old_loop Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 16:08:27 2009 @@ -145,7 +145,7 @@ return "" % (self.source, flags) -def optimize_loop(metainterp, old_loops, operations): +def optimize_loop(metainterp, old_loops, loop): if not metainterp._specialize: # for tests only if old_loops: return old_loops[0] @@ -153,11 +153,11 @@ return None # This does "Perfect specialization" as per doc/jitpl5.txt. - perfect_specializer = PerfectSpecializer(operations) + perfect_specializer = PerfectSpecializer(loop) perfect_specializer.find_nodes() perfect_specializer.intersect_input_and_output() for old_loop in old_loops: - if perfect_specializer.match_exactly(old_loop.operations): + if perfect_specializer.match_exactly(old_loop): return old_loop perfect_specializer.optimize_loop() return None @@ -177,8 +177,8 @@ class PerfectSpecializer(object): - def __init__(self, operations): - self.operations = operations + def __init__(self, loop): + self.loop = loop self.nodes = {} self.dependency_graph = [] @@ -192,10 +192,10 @@ def find_nodes(self): # Steps (1) and (2) - for box in self.operations[0].args: + for box in self.loop.operations[0].args: self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) - for op in self.operations[1:-1]: + for op in self.loop.operations[1:-1]: opname = op.opname if opname == 'new_with_vtable': box = op.results[0] @@ -252,13 +252,13 @@ self.nodes[box] = InstanceNode(box, escaped=True) def recursively_find_escaping_values(self): - assert self.operations[0].opname == 'merge_point' - end_args = self.operations[-1].args + assert self.loop.operations[0].opname == 'merge_point' + end_args = self.loop.operations[-1].args memo = {} for i in range(len(end_args)): self.nodes[end_args[i]].escape_if_startbox(memo) for i in range(len(end_args)): - box = self.operations[0].args[i] + box = self.loop.operations[0].args[i] other_box = end_args[i] self.nodes[box].add_to_dependency_graph(self.nodes[other_box], self.dependency_graph) @@ -275,12 +275,14 @@ def intersect_input_and_output(self): # Step (3) self.recursively_find_escaping_values() - assert self.operations[0].opname == 'merge_point' - assert self.operations[-1].opname == 'jump' + mp = self.loop.operations[0] + jump = self.loop.operations[-1] + assert mp.opname == 'merge_point' + assert jump.opname == 'jump' specnodes = [] - for i in range(len(self.operations[0].args)): - enternode = self.nodes[self.operations[0].args[i]] - leavenode = self.getnode(self.operations[-1].args[i]) + for i in range(len(mp.args)): + enternode = self.nodes[mp.args[i]] + leavenode = self.getnode(jump.args[i]) specnodes.append(enternode.intersect(leavenode)) self.specnodes = specnodes @@ -326,18 +328,19 @@ def optimize_loop(self): newoperations = [] - if self.operations[0].opname == 'merge_point': - assert len(self.operations[0].args) == len(self.specnodes) + mp = self.loop.operations[0] + if mp.opname == 'merge_point': + assert len(mp.args) == len(self.specnodes) for i in range(len(self.specnodes)): - box = self.operations[0].args[i] + box = mp.args[i] self.specnodes[i].mutate_nodes(self.nodes[box]) else: - assert self.operations[0].opname == 'catch' - for box in self.operations[0].args: + assert mp.opname == 'catch' + for box in mp.args: self.nodes[box].cls = None assert not self.nodes[box].virtual - for op in self.operations: + for op in self.loop.operations: opname = op.opname if opname == 'merge_point': args = self.expanded_version_of(op.args) @@ -429,9 +432,10 @@ newoperations.append(op) newoperations[0].specnodes = self.specnodes - self.operations[:] = newoperations + self.loop.operations = newoperations - def match_exactly(self, old_operations): + def match_exactly(self, old_loop): + old_operations = old_loop.operations old_mp = old_operations[0] assert len(old_mp.specnodes) == len(self.specnodes) for i in range(len(self.specnodes)): @@ -443,7 +447,7 @@ def match(self, old_operations): old_mp = old_operations[0] - jump_op = self.operations[-1] + jump_op = self.loop.operations[-1] assert jump_op.opname == 'jump' assert len(old_mp.specnodes) == len(jump_op.args) for i in range(len(old_mp.specnodes)): @@ -455,7 +459,7 @@ def adapt_for_match(self, old_operations): old_mp = old_operations[0] - jump_op = self.operations[-1] + jump_op = self.loop.operations[-1] self.specnodes = old_mp.specnodes for i in range(len(old_mp.specnodes)): old_specnode = old_mp.specnodes[i] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 16:08:27 2009 @@ -32,6 +32,10 @@ # ____________________________________________________________ +class Loop(object): + def __init__(self, operations): + self.operations = operations + class Any(object): def __eq__(self, other): return True @@ -95,7 +99,7 @@ ] def test_A_find_nodes(): - spec = PerfectSpecializer(A.ops) + spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() assert spec.nodes[A.sum] is not spec.nodes[A.sum2] assert spec.nodes[A.n1] is not spec.nodes[A.n2] @@ -105,7 +109,7 @@ assert not spec.nodes[A.n2].escaped def test_A_intersect_input_and_output(): - spec = PerfectSpecializer(A.ops) + spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() assert len(spec.specnodes) == 2 @@ -117,16 +121,15 @@ assert isinstance(spec_n.fields[0][1], NotSpecNode) def test_A_optimize_loop(): - operations = A.ops[:] - spec = PerfectSpecializer(operations) + spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert equaloplists(operations, [ - MergePoint('merge_point', [A.sum, A.v], []), - ResOperation('int_sub', [A.v, ConstInt(1)], [A.v2]), - ResOperation('int_add', [A.sum, A.v], [A.sum2]), - Jump('jump', [A.sum2, A.v2], []), + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [A.sum, A.v], []), + ResOperation('int_sub', [A.v, ConstInt(1)], [A.v2]), + ResOperation('int_add', [A.sum, A.v], [A.sum2]), + Jump('jump', [A.sum2, A.v2], []), ]) # ____________________________________________________________ @@ -147,7 +150,7 @@ ] def test_B_find_nodes(): - spec = PerfectSpecializer(B.ops) + spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() assert spec.nodes[B.n1].cls.source.value == node_vtable_adr assert not spec.nodes[B.n1].escaped @@ -155,7 +158,7 @@ assert spec.nodes[B.n2].escaped def test_B_intersect_input_and_output(): - spec = PerfectSpecializer(B.ops) + spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() spec.intersect_input_and_output() assert len(spec.specnodes) == 2 @@ -165,12 +168,11 @@ assert spec_n.known_class.value == node_vtable_adr def test_B_optimize_loop(): - operations = B.ops[:] - spec = PerfectSpecializer(operations) + spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert equaloplists(operations, [ + equaloplists(spec.loop.operations, [ MergePoint('merge_point', [B.sum, B.n1], []), # guard_class is gone ResOperation('getfield_gc', [B.n1, ConstInt(B.ofs_value)], [B.v]), @@ -202,14 +204,14 @@ ] def test_C_find_nodes(): - spec = PerfectSpecializer(C.ops) + spec = PerfectSpecializer(Loop(C.ops)) spec.find_nodes() assert spec.nodes[C.n1].cls.source.value == node_vtable_adr assert spec.nodes[C.n1].escaped assert spec.nodes[C.n2].cls.source.value == node_vtable_adr def test_C_intersect_input_and_output(): - spec = PerfectSpecializer(C.ops) + spec = PerfectSpecializer(Loop(C.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[C.n2].escaped @@ -220,12 +222,11 @@ assert spec_n.known_class.value == node_vtable_adr def test_C_optimize_loop(): - operations = C.ops[:] - spec = PerfectSpecializer(operations) + spec = PerfectSpecializer(Loop(C.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert equaloplists(operations, [ + equaloplists(spec.loop.operations, [ MergePoint('merge_point', [C.sum, C.n1], []), # guard_class is gone ResOperation('getfield_gc', [C.n1, ConstInt(C.ofs_value)], [C.v]), @@ -257,7 +258,7 @@ ] def test_D_intersect_input_and_output(): - spec = PerfectSpecializer(D.ops) + spec = PerfectSpecializer(Loop(D.ops)) spec.find_nodes() py.test.raises(CancelInefficientLoop, spec.intersect_input_and_output) @@ -280,12 +281,11 @@ ops[-2].liveboxes = [sum2, n2] def test_E_optimize_loop(): - operations = E.ops[:] - spec = PerfectSpecializer(operations) + spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert equaloplists(operations, [ + equaloplists(spec.loop.operations, [ MergePoint('merge_point', [E.sum, E.v], []), # guard_class is gone ResOperation('int_sub', [E.v, ConstInt(1)], [E.v2]), @@ -293,7 +293,7 @@ ResOperation('guard_true', [E.v2], []), Jump('jump', [E.sum2, E.v2], []), ]) - guard_op = operations[-2] + guard_op = spec.loop.operations[-2] assert guard_op.opname == 'guard_true' assert guard_op.liveboxes == [E.sum2, E.v2] vt = cpu.cast_adr_to_int(node_vtable_adr) @@ -312,12 +312,11 @@ else: return [] - operations = E.ops[:] - spec = PerfectSpecializer(operations) + spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - guard_op = operations[-2] + guard_op = spec.loop.operations[-2] fake_history = FakeHistory() v_sum_b = BoxInt(13) v_v_b = BoxInt(14) @@ -363,19 +362,18 @@ ops[-6].liveboxes = liveboxes[:] def test_F_find_nodes(): - spec = PerfectSpecializer(F.ops) + spec = PerfectSpecializer(Loop(F.ops)) spec.find_nodes() assert not spec.nodes[F.n1].escaped assert not spec.nodes[F.n2].escaped def test_F_optimize_loop(): - operations = F.ops[:] - spec = PerfectSpecializer(operations) + spec = PerfectSpecializer(Loop(F.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[F.n3].escaped spec.optimize_loop() - assert equaloplists(operations, [ + equaloplists(spec.loop.operations, [ MergePoint('merge_point', [F.sum, F.v, F.n3], []), ResOperation('int_sub', [F.v, ConstInt(1)], [F.v2]), ResOperation('int_add', [F.sum, F.v], [F.sum2]), @@ -409,12 +407,11 @@ ops[-2].liveboxes = [sum2, n2] def test_G_optimize_loop(): - operations = G.ops[:] - spec = PerfectSpecializer(operations) + spec = PerfectSpecializer(Loop(G.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert equaloplists(operations, [ + equaloplists(spec.loop.operations, [ MergePoint('merge_point', [G.sum, G.v], []), # guard_class is gone ResOperation('int_sub', [G.v, ConstInt(1)], [G.v2]), @@ -422,7 +419,7 @@ ResOperation('guard_true', [G.v2], []), Jump('jump', [G.sum2, ConstInt(124)], []), ]) - guard_op = operations[-2] + guard_op = spec.loop.operations[-2] assert guard_op.opname == 'guard_true' assert guard_op.liveboxes == [G.sum2, ConstInt(124)] vt = cpu.cast_adr_to_int(node_vtable_adr) @@ -457,7 +454,7 @@ ] def test_H_intersect_input_and_output(): - spec = PerfectSpecializer(H.ops) + spec = PerfectSpecializer(Loop(H.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[H.n0].escaped @@ -485,7 +482,7 @@ ] def test_I_intersect_input_and_output(): - spec = PerfectSpecializer(I.ops) + spec = PerfectSpecializer(Loop(I.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[I.n0].escaped @@ -515,10 +512,40 @@ ] def test_J_intersect_input_and_output(): - spec = PerfectSpecializer(J.ops) + spec = PerfectSpecializer(Loop(J.ops)) spec.find_nodes() spec.intersect_input_and_output() assert not spec.nodes[J.n0].escaped assert spec.nodes[J.n1].escaped assert not spec.nodes[J.n2].escaped +# ____________________________________________________________ + +class K: + locals().update(A.__dict__) # :-) + sum3 = BoxInt(3) + v3 = BoxInt(4) + ops = [ + MergePoint('merge_point', [sum, n1], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('int_add', [sum, v], [sum2]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), + ResOperation('int_add', [sum2, v3], [sum3]), + Jump('jump', [sum2, n1], []), + ] + +def test_K_optimize_loop(): + py.test.skip("incomplete test") + spec = PerfectSpecializer(Loop(K.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + assert equaloplists(operations, [ + MergePoint('merge_point', [K.sum, K.v], []), + ResOperation('int_sub', [K.v, ConstInt(1)], [K.v2]), + ResOperation('int_add', [K.sum, K.v], [K.sum2]), + Jump('jump', [K.sum2, K.v2], []), + ]) + Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Fri Feb 13 16:08:27 2009 @@ -11,7 +11,7 @@ NotSpecNode) from pypy.jit.metainterp.virtualizable import VirtualizableDesc from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, - equaloplists) + equaloplists, Loop) # ____________________________________________________________ @@ -93,12 +93,12 @@ ops[1].vdesc = xy_desc def test_A_find_nodes(): - spec = PerfectSpecializer(A.ops) + spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() assert spec.nodes[A.fr].virtualized def test_A_intersect_input_and_output(): - spec = PerfectSpecializer(A.ops) + spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[A.fr].escaped @@ -108,17 +108,16 @@ assert isinstance(spec.specnodes[1], VirtualizableSpecNode) def test_A_optimize_loop(): - operations = A.ops[:] - spec = PerfectSpecializer(operations) + spec = PerfectSpecializer(Loop(A.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert equaloplists(operations, [ - MergePoint('merge_point', [A.sum, A.fr, A.v], []), - ResOperation('int_sub', [A.v, ConstInt(1)], [A.v2]), - ResOperation('int_add', [A.sum, A.v], [A.sum2]), - Jump('jump', [A.sum2, A.fr, A.v2], []), - ]) + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [A.sum, A.fr, A.v], []), + ResOperation('int_sub', [A.v, ConstInt(1)], [A.v2]), + ResOperation('int_add', [A.sum, A.v], [A.sum2]), + Jump('jump', [A.sum2, A.fr, A.v2], []), + ]) # ____________________________________________________________ @@ -145,7 +144,7 @@ ops[1].vdesc = xy_desc def test_B_intersect_input_and_output(): - spec = PerfectSpecializer(B.ops) + spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[B.fr].escaped @@ -180,7 +179,7 @@ ops[1].vdesc = xy_desc def test_C_intersect_input_and_output(): - spec = PerfectSpecializer(C.ops) + spec = PerfectSpecializer(Loop(C.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[C.fr].escaped From fijal at codespeak.net Fri Feb 13 16:20:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 16:20:34 +0100 (CET) Subject: [pypy-svn] r61834 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090213152034.C9A1F169E25@codespeak.net> Author: fijal Date: Fri Feb 13 16:20:34 2009 New Revision: 61834 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: In-progress, tests about laziness Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 16:20:34 2009 @@ -533,19 +533,86 @@ ResOperation('int_add', [sum, v], [sum2]), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), ResOperation('int_add', [sum2, v3], [sum3]), - Jump('jump', [sum2, n1], []), + Jump('jump', [sum3, n1], []), ] def test_K_optimize_loop(): - py.test.skip("incomplete test") + py.test.skip("in-progress") spec = PerfectSpecializer(Loop(K.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - assert equaloplists(operations, [ - MergePoint('merge_point', [K.sum, K.v], []), - ResOperation('int_sub', [K.v, ConstInt(1)], [K.v2]), - ResOperation('int_add', [K.sum, K.v], [K.sum2]), - Jump('jump', [K.sum2, K.v2], []), - ]) - + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [K.sum, K.n1, K.v], []), + ResOperation('int_sub', [K.v, ConstInt(1)], [K.v2]), + ResOperation('int_add', [K.sum, K.v], [K.sum2]), + ResOperation('int_add', [K.sum2, K.v], [K.sum3]), + Jump('jump', [K.sum3, K.n1, K.v], []), + ]) + assert spec.loop.prologue == [(K.n1, K.v, K.ofs_value)] + +# ____________________________________________________________ + +class L: + locals().update(A.__dict__) # :-) + sum3 = BoxInt(3) + v3 = BoxInt(4) + ops = [ + MergePoint('merge_point', [sum, n1], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('int_add', [sum, v], [sum2]), + ResOperation('escape', [n1], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), + ResOperation('int_add', [sum2, v3], [sum3]), + Jump('jump', [sum3, n1], []), + ] + +def test_L_optimize_loop(): + py.test.skip("in-progress") + spec = PerfectSpecializer(Loop(L.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [L.sum, L.n1, L.v], []), + ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), + ResOperation('int_add', [L.sum, L.v], [L.sum2]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), + ResOperation('int_add', [L.sum2, L.v3], [L.sum3]), + Jump('jump', [L.sum3, L.n1, L.v3], []), + ]) + assert spec.loop.prologue == [(L.n1, L.v, L.ofs_value)] + +# ____________________________________________________________ + +class M: + locals().update(A.__dict__) # :-) + sum3 = BoxInt(3) + v3 = BoxInt(4) + ops = [ + MergePoint('merge_point', [sum, n1], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('int_add', [sum, v], [sum2]), + ResOperation('escape', [n1], []), + Jump('jump', [sum2, n1], []), + ] + +def test_M_optimize_loop(): + py.test.skip("in-progress") + spec = PerfectSpecializer(Loop(L.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [L.sum, L.n1, L.v], []), + ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), + ResOperation('int_add', [L.sum, L.v], [L.sum2]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), + Jump('jump', [L.sum2, L.n1, L.v3], []), + ]) + assert spec.loop.prologue == [(L.n1, L.v, L.ofs_value)] + From arigo at codespeak.net Fri Feb 13 16:21:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Feb 2009 16:21:17 +0100 (CET) Subject: [pypy-svn] r61835 - pypy/branch/pyjitpl5/pypy/jit/backend/x86 Message-ID: <20090213152117.79349169E25@codespeak.net> Author: arigo Date: Fri Feb 13 16:21:16 2009 New Revision: 61835 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/ri386.py - copied unchanged from r61746, pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/ri386setup.py - copied unchanged from r61746, pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386setup.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Log: Fix some (random) imports by copying ri386*.py from the oo-jit branch. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Feb 13 16:21:16 2009 @@ -1,6 +1,6 @@ import sys import ctypes -from pypy.jit.codegen.i386.ri386 import * +from pypy.jit.backend.x86.ri386 import * from codegen386 import symbolic from history import Const, ConstInt, Box, MergePoint from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr @@ -10,8 +10,8 @@ from codegen386.regalloc import RegAlloc, FRAMESIZE, WORD, REGS from codegen386.regalloc import arg_pos, lower_byte, stack_pos, Perform from pypy.rlib.objectmodel import we_are_translated, specialize -from pypy.jit.codegen.i386 import codebuf -from pypy.jit.codegen.i386.rgenop import gc_malloc_fnaddr +from pypy.jit.backend.x86 import codebuf +from pypy.jit.backend.x86.rgenop import gc_malloc_fnaddr # our calling convention - we pass three first args as edx, ecx and eax # and the rest stays on stack Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Feb 13 16:21:16 2009 @@ -4,7 +4,7 @@ from history import Box, Const, ConstInt, ConstPtr, ResOperation, MergePoint,\ ConstAddr -from pypy.jit.codegen.i386.ri386 import * +from pypy.jit.backend.x86.ri386 import * from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable From afa at codespeak.net Fri Feb 13 16:32:46 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Feb 2009 16:32:46 +0100 (CET) Subject: [pypy-svn] r61836 - in pypy/trunk/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20090213153246.0BDCC169E25@codespeak.net> Author: afa Date: Fri Feb 13 16:32:44 2009 New Revision: 61836 Modified: pypy/trunk/pypy/lib/_ctypes/function.py pypy/trunk/pypy/lib/app_test/ctypes_tests/support.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_checkretval.py Log: Implement _check_retval_, and unskip some tests Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Fri Feb 13 16:32:44 2009 @@ -55,7 +55,10 @@ not callable(restype): raise TypeError("Expected ctypes type, got %s" % (restype,)) self._restype_ = restype - restype = property(_getrestype, _setrestype) + def _delrestype(self): + self._ptr = None + del self._restype_ + restype = property(_getrestype, _setrestype, _delrestype) def _ffishapes(self, args, restype): argtypes = [arg._ffiargshape for arg in args] @@ -260,6 +263,23 @@ If there is no OUT parameter, return the actual function result If there is one OUT parameter, return it If there are many OUT parameters, return a tuple""" + + retval = None + + if restype is not None: + checker = getattr(self.restype, '_check_retval_', None) + if checker: + val = restype(resbuffer[0]) + # the original ctypes seems to make the distinction between + # classes defining a new type, and their subclasses + if '_type_' in restype.__dict__: + val = val.value + retval = checker(val) + elif not isinstance(restype, _CDataMeta): + retval = restype(resbuffer[0]) + else: + retval = restype._CData_retval(resbuffer) + results = [] if self._paramflags: for argtype, (_, obj), paramflag in zip(argtypes[1:], argsandobjs[1:], @@ -282,10 +302,7 @@ return tuple(results) # No output parameter, return the actual function result. - if restype is not None: - if not isinstance(restype, _CDataMeta): - return restype(resbuffer[0]) - return restype._CData_retval(resbuffer) + return retval def __del__(self): if self._needs_free: Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/support.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/support.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/support.py Fri Feb 13 16:32:44 2009 @@ -8,7 +8,7 @@ def setup_class(cls): try: - import _rawffi + import _rawffi except ImportError: py.test.skip("these tests are white-box tests for pypy _rawffi based ctypes impl") Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_checkretval.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_checkretval.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_checkretval.py Fri Feb 13 16:32:44 2009 @@ -16,8 +16,6 @@ class TestRetval: def test_checkretval(self): - py.test.skip("_check_retval_ is not supported") - assert 42 == dll._testfunc_p_p(42) dll._testfunc_p_p.restype = CHECKED @@ -35,7 +33,6 @@ pass else: def test_oledll(self): - py.test.skip("_check_retval_ is not supported") raises(WindowsError, - oledll.oleaut32.CreateTypeLib2, - 0, 0, 0) + oledll.oleaut32.CreateTypeLib2, + 0, 0, 0) From arigo at codespeak.net Fri Feb 13 16:33:40 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 13 Feb 2009 16:33:40 +0100 (CET) Subject: [pypy-svn] r61837 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090213153340.953E1169E2B@codespeak.net> Author: arigo Date: Fri Feb 13 16:33:40 2009 New Revision: 61837 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Fix tests(?) and add a comment. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 16:33:40 2009 @@ -579,6 +579,7 @@ MergePoint('merge_point', [L.sum, L.n1, L.v], []), ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), ResOperation('int_add', [L.sum, L.v], [L.sum2]), + ResOperation('escape', [L.n1], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), ResOperation('int_add', [L.sum2, L.v3], [L.sum3]), Jump('jump', [L.sum3, L.n1, L.v3], []), @@ -607,10 +608,14 @@ spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() + # XXX why do we expect that? I'd rather say that n1 is passed around + # as an escaped until the first getfield_gc instead of generating + # a getfield_gc eagerly after the 'escape'... equaloplists(spec.loop.operations, [ MergePoint('merge_point', [L.sum, L.n1, L.v], []), ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), ResOperation('int_add', [L.sum, L.v], [L.sum2]), + ResOperation('escape', [L.n1], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), Jump('jump', [L.sum2, L.n1, L.v3], []), ]) From fijal at codespeak.net Fri Feb 13 16:57:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 16:57:27 +0100 (CET) Subject: [pypy-svn] r61838 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213155727.06778169E51@codespeak.net> Author: fijal Date: Fri Feb 13 16:57:26 2009 New Revision: 61838 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: A first go. This already simplifies stuff a bit, but probably also breaks something else. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 16:57:26 2009 @@ -72,6 +72,7 @@ self.cls = None self.origfields = {} self.curfields = {} + self.cleanfields = {} def escape_if_startbox(self, memo): if self in memo: @@ -142,6 +143,7 @@ if self.const: flags += 'c' if self.virtual: flags += 'v' if self.virtualized: flags += 'V' + if self.dirty: flags += 'd' return "" % (self.source, flags) @@ -376,11 +378,17 @@ continue elif opname == 'getfield_gc': instnode = self.nodes[op.args[0]] + ofs = op.args[1].getint() if instnode.virtual or instnode.virtualized: - ofs = op.args[1].getint() assert ofs in instnode.curfields # xxx self.nodes[op.results[0]] = instnode.curfields[ofs] continue + else: + if ofs in instnode.cleanfields: + self.nodes[op.results[0]] = instnode.cleanfields[ofs] + continue + else: + instnode.cleanfields[ofs] = InstanceNode(op.results[0]) elif opname == 'new_with_vtable': # self.nodes[op.results[0]] keep the value from Steps (1,2) instnode = self.nodes[op.results[0]] @@ -415,6 +423,7 @@ self.nodes[box] = instnode continue # default handling of arguments and return value(s) + self.cleanup_clean_fields(op.args) op = self.replace_arguments(op) if opname in always_pure_operations: for box in op.args: @@ -434,6 +443,11 @@ newoperations[0].specnodes = self.specnodes self.loop.operations = newoperations + def cleanup_clean_fields(self, args): + for arg in args: + if not isinstance(arg, Const): + self.nodes[arg].cleanfields = {} + def match_exactly(self, old_loop): old_operations = old_loop.operations old_mp = old_operations[0] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 16:57:26 2009 @@ -521,6 +521,38 @@ # ____________________________________________________________ +class K0: + locals().update(A.__dict__) # :-) + sum3 = BoxInt(3) + v3 = BoxInt(4) + ops = [ + MergePoint('merge_point', [sum, n1], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('int_add', [sum, v], [sum2]), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), + ResOperation('int_add', [sum2, v3], [sum3]), + ResOperation('escape', [n1], []), + Jump('jump', [sum3, n1], []), + ] + +def test_K0_optimize_loop(): + spec = PerfectSpecializer(Loop(K0.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [K0.sum, K0.n1], []), + ResOperation('getfield_gc', [K0.n1, ConstInt(K0.ofs_value)], [K0.v]), + ResOperation('int_sub', [K0.v, ConstInt(1)], [K0.v2]), + ResOperation('int_add', [K0.sum, K0.v], [K0.sum2]), + ResOperation('int_add', [K0.sum2, K0.v], [K0.sum3]), + ResOperation('escape', [K0.n1], []), + Jump('jump', [K0.sum3, K0.n1], []), + ]) + + class K: locals().update(A.__dict__) # :-) sum3 = BoxInt(3) @@ -537,7 +569,6 @@ ] def test_K_optimize_loop(): - py.test.skip("in-progress") spec = PerfectSpecializer(Loop(K.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -549,7 +580,6 @@ ResOperation('int_add', [K.sum2, K.v], [K.sum3]), Jump('jump', [K.sum3, K.n1, K.v], []), ]) - assert spec.loop.prologue == [(K.n1, K.v, K.ofs_value)] # ____________________________________________________________ @@ -570,7 +600,6 @@ ] def test_L_optimize_loop(): - py.test.skip("in-progress") spec = PerfectSpecializer(Loop(L.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -603,21 +632,17 @@ ] def test_M_optimize_loop(): - py.test.skip("in-progress") spec = PerfectSpecializer(Loop(L.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() - # XXX why do we expect that? I'd rather say that n1 is passed around - # as an escaped until the first getfield_gc instead of generating - # a getfield_gc eagerly after the 'escape'... equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [L.sum, L.n1, L.v], []), + MergePoint('merge_point', [L.sum, L.n1], []), + ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], [L.v]), ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), ResOperation('int_add', [L.sum, L.v], [L.sum2]), ResOperation('escape', [L.n1], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), - Jump('jump', [L.sum2, L.n1, L.v3], []), + Jump('jump', [L.sum2, L.n1], []), ]) - assert spec.loop.prologue == [(L.n1, L.v, L.ofs_value)] + assert spec.loop.prologue == [] From fijal at codespeak.net Fri Feb 13 17:13:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 17:13:09 +0100 (CET) Subject: [pypy-svn] r61839 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090213161309.0F03D169E8D@codespeak.net> Author: fijal Date: Fri Feb 13 17:13:08 2009 New Revision: 61839 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py Log: two more ops. only for sideeffects/canfold attrs Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py Fri Feb 13 17:13:08 2009 @@ -488,6 +488,8 @@ 'ooupcast': LLOp(oo=True, canfold=True), 'oodowncast': LLOp(oo=True, canfold=True), 'oononnull': LLOp(oo=True, canfold=True), + 'ooisnot': LLOp(oo=True, canfold=True), + 'ooisnull': LLOp(oo=True, canfold=True), 'oois': LLOp(oo=True, canfold=True), 'instanceof': LLOp(oo=True, canfold=True), 'classof': LLOp(oo=True, canfold=True), From fijal at codespeak.net Fri Feb 13 17:30:26 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 17:30:26 +0100 (CET) Subject: [pypy-svn] r61840 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213163026.331F8169E3A@codespeak.net> Author: fijal Date: Fri Feb 13 17:30:23 2009 New Revision: 61840 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: A first go at having it right. I think we need to twist logic a bit in order to know *before* optimize_loop what we're going to do Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Fri Feb 13 17:30:23 2009 @@ -72,6 +72,12 @@ for _opname, _opdesc in lloperation.LL_OPERATIONS.iteritems(): if _opdesc.canfold: always_pure_operations[_opname] = None + if not _opdesc.sideeffects: + operations_without_side_effects[_opname] = None + # XXX fish fish fish + operations_without_side_effects['getfield_gc'] = None + +operations_without_side_effects = {} always_pure_operations = {} setup() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 17:30:23 2009 @@ -1,6 +1,7 @@ from pypy.jit.metainterp.history import (Box, Const, ConstInt, MergePoint, ResOperation, Jump) -from pypy.jit.metainterp.heaptracker import always_pure_operations +from pypy.jit.metainterp.heaptracker import (always_pure_operations, + operations_without_side_effects) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, VirtualInstanceSpecNode, VirtualizableSpecNode, @@ -73,6 +74,7 @@ self.origfields = {} self.curfields = {} self.cleanfields = {} + self.dirtyfields = {} def escape_if_startbox(self, memo): if self in memo: @@ -143,7 +145,6 @@ if self.const: flags += 'c' if self.virtual: flags += 'v' if self.virtualized: flags += 'V' - if self.dirty: flags += 'd' return "" % (self.source, flags) @@ -350,6 +351,7 @@ newoperations.append(op) continue elif opname == 'jump': + self.cleanup_field_caches(newoperations) args = self.expanded_version_of(op.args) op = Jump('jump', args, []) newoperations.append(op) @@ -383,12 +385,11 @@ assert ofs in instnode.curfields # xxx self.nodes[op.results[0]] = instnode.curfields[ofs] continue + elif ofs in instnode.cleanfields: + self.nodes[op.results[0]] = instnode.cleanfields[ofs] + continue else: - if ofs in instnode.cleanfields: - self.nodes[op.results[0]] = instnode.cleanfields[ofs] - continue - else: - instnode.cleanfields[ofs] = InstanceNode(op.results[0]) + instnode.cleanfields[ofs] = InstanceNode(op.results[0]) elif opname == 'new_with_vtable': # self.nodes[op.results[0]] keep the value from Steps (1,2) instnode = self.nodes[op.results[0]] @@ -402,11 +403,15 @@ elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] + ofs = op.args[1].getint() if instnode.virtual or instnode.virtualized: - ofs = op.args[1].getint() instnode.curfields[ofs] = valuenode - continue - assert not valuenode.virtual + else: + assert not valuenode.virtual + instnode.cleanfields[ofs] = self.nodes[op.args[2]] + instnode.dirtyfields[ofs] = self.nodes[op.args[2]] + # we never perform this operation here, note + continue elif opname == 'ooisnull' or opname == 'oononnull': instnode = self.nodes[op.args[0]] if instnode.virtual: @@ -423,7 +428,6 @@ self.nodes[box] = instnode continue # default handling of arguments and return value(s) - self.cleanup_clean_fields(op.args) op = self.replace_arguments(op) if opname in always_pure_operations: for box in op.args: @@ -435,6 +439,8 @@ instnode = InstanceNode(box.constbox()) self.nodes[box] = instnode continue + elif opname not in operations_without_side_effects: + self.cleanup_field_caches(newoperations) for box in op.results: instnode = InstanceNode(box) self.nodes[box] = instnode @@ -443,10 +449,14 @@ newoperations[0].specnodes = self.specnodes self.loop.operations = newoperations - def cleanup_clean_fields(self, args): - for arg in args: - if not isinstance(arg, Const): - self.nodes[arg].cleanfields = {} + def cleanup_field_caches(self, newoperations): + # we need to invalidate everything + for node in self.nodes.values(): + for ofs, valuenode in node.dirtyfields.items(): + newoperations.append(ResOperation('setfield_gc', + [node.source, ConstInt(ofs), valuenode.source], [])) + node.dirtyfields = {} + node.cleanfields = {} def match_exactly(self, old_loop): old_operations = old_loop.operations Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 17:30:23 2009 @@ -553,6 +553,41 @@ ]) +class K1: + locals().update(A.__dict__) # :-) + sum3 = BoxInt(3) + v3 = BoxInt(4) + ops = [ + MergePoint('merge_point', [sum, n1], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('int_add', [sum, v], [sum2]), + ResOperation('setfield_gc', [n1, ConstInt(ofs_value), sum], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), + ResOperation('int_add', [sum2, v3], [sum3]), + ResOperation('escape', [n1], []), + Jump('jump', [sum3, n1], []), + ] + +def test_K1_optimize_loop(): + spec = PerfectSpecializer(Loop(K1.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [K1.sum, K1.n1], []), + ResOperation('getfield_gc', [K1.n1, ConstInt(K1.ofs_value)], [K1.v]), + ResOperation('int_sub', [K1.v, ConstInt(1)], [K1.v2]), + ResOperation('int_add', [K1.sum, K1.v], [K1.sum2]), + ResOperation('int_add', [K1.sum2, K1.sum], [K1.sum3]), + ResOperation('setfield_gc', [K1.n1, ConstInt(K1.ofs_value), K1.sum], + []), + ResOperation('escape', [K1.n1], []), + Jump('jump', [K1.sum3, K1.n1], []), + ]) + + class K: locals().update(A.__dict__) # :-) sum3 = BoxInt(3) From getxsick at codespeak.net Fri Feb 13 17:59:02 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Fri, 13 Feb 2009 17:59:02 +0100 (CET) Subject: [pypy-svn] r61841 - pypy/trunk/pypy/doc/config Message-ID: <20090213165902.56B93169E1F@codespeak.net> Author: getxsick Date: Fri Feb 13 17:59:00 2009 New Revision: 61841 Added: pypy/trunk/pypy/doc/config/objspace.usemodules._locale.txt Log: added for _locale module Added: pypy/trunk/pypy/doc/config/objspace.usemodules._locale.txt ============================================================================== --- (empty file) +++ pypy/trunk/pypy/doc/config/objspace.usemodules._locale.txt Fri Feb 13 17:59:00 2009 @@ -0,0 +1,3 @@ +Use the '_locale' module. +This module runs _locale written in RPython (instead of ctypes version). +It's not really finished yet. From fijal at codespeak.net Fri Feb 13 18:22:17 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 18:22:17 +0100 (CET) Subject: [pypy-svn] r61844 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213172217.7516D169E1C@codespeak.net> Author: fijal Date: Fri Feb 13 18:22:16 2009 New Revision: 61844 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Do the right thing in case of guard failure. A bit of a hack, because we need to fish correct values in case they're not in liveboxes (because of arbitrary side effects) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 18:22:16 2009 @@ -6,6 +6,7 @@ VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode) +from pypy.rlib.objectmodel import we_are_translated class CancelInefficientLoop(Exception): pass @@ -308,6 +309,26 @@ for box in old_boxes: indices.append(storage.deal_with_box(box, self.nodes, liveboxes, memo)) + rev_boxes = {} + for i in range(len(liveboxes)): + box = liveboxes[i] + rev_boxes[box] = i + for node in self.nodes.values(): + for ofs, subnode in node.dirtyfields.items(): + box = node.source + if box not in rev_boxes: + rev_boxes[box] = len(liveboxes) + liveboxes.append(box) + index = ~rev_boxes[box] + fieldbox = subnode.source + if fieldbox not in rev_boxes: + rev_boxes[fieldbox] = len(liveboxes) + liveboxes.append(fieldbox) + fieldindex = ~rev_boxes[fieldbox] + storage.setfields.append((index, ofs, fieldindex)) + if not we_are_translated(): + items = [box for box in liveboxes if isinstance(box, Box)] + assert len(dict.fromkeys(items)) == len(items) storage.indices = indices op.args = self.new_arguments(op) op.liveboxes = liveboxes @@ -351,7 +372,7 @@ newoperations.append(op) continue elif opname == 'jump': - self.cleanup_field_caches(newoperations) + self.adjust_operations_before_jump(newoperations) args = self.expanded_version_of(op.args) op = Jump('jump', args, []) newoperations.append(op) @@ -449,6 +470,9 @@ newoperations[0].specnodes = self.specnodes self.loop.operations = newoperations + def adjust_operations_before_jump(self, newoperations): + self.cleanup_field_caches(newoperations) + def cleanup_field_caches(self, newoperations): # we need to invalidate everything for node in self.nodes.values(): @@ -518,4 +542,5 @@ newboxes.append(boxes_from_frame[~index]) else: newboxes.append(allocated_boxes[index]) + return newboxes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Fri Feb 13 18:22:16 2009 @@ -26,6 +26,30 @@ assert res == 84 self.check_loop_count(1) + def test_loop_with_delayed_setfield(self): + myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res', 'a']) + class A(object): + def __init__(self): + self.x = 3 + + def f(x, y): + res = 0 + a = A() + while y > 0: + myjitdriver.can_enter_jit(x=x, y=y, res=res, a=a) + myjitdriver.jit_merge_point(x=x, y=y, res=res, a=a) + a.x = y + if y < 3: + return a.x + res += a.x + y -= 1 + return res * 2 + res = self.meta_interp(f, [6, 13]) + assert res == f(6, 13) + self.check_loop_count(1) + if self.specialize: + self.check_loops(getfield_gc = 0, setfield_gc = 1) + def test_loop_with_two_paths(self): myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) def g(y, x): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 18:22:16 2009 @@ -139,6 +139,7 @@ ops = [ MergePoint('merge_point', [sum, n1], []), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('escape', [n1], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -153,7 +154,7 @@ spec = PerfectSpecializer(Loop(B.ops)) spec.find_nodes() assert spec.nodes[B.n1].cls.source.value == node_vtable_adr - assert not spec.nodes[B.n1].escaped + assert spec.nodes[B.n1].escaped assert spec.nodes[B.n2].cls.source.value == node_vtable_adr assert spec.nodes[B.n2].escaped @@ -175,6 +176,7 @@ equaloplists(spec.loop.operations, [ MergePoint('merge_point', [B.sum, B.n1], []), # guard_class is gone + ResOperation('escape', [B.n1], []), ResOperation('getfield_gc', [B.n1, ConstInt(B.ofs_value)], [B.v]), ResOperation('int_sub', [B.v, ConstInt(1)], [B.v2]), ResOperation('int_add', [B.sum, B.v], [B.sum2]), @@ -604,6 +606,7 @@ ] def test_K_optimize_loop(): + py.test.skip("not yet") spec = PerfectSpecializer(Loop(K.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -635,6 +638,7 @@ ] def test_L_optimize_loop(): + py.test.skip("not yet") spec = PerfectSpecializer(Loop(L.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -667,6 +671,7 @@ ] def test_M_optimize_loop(): + py.test.skip("not yet") spec = PerfectSpecializer(Loop(L.ops)) spec.find_nodes() spec.intersect_input_and_output() From getxsick at codespeak.net Fri Feb 13 19:32:01 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Fri, 13 Feb 2009 19:32:01 +0100 (CET) Subject: [pypy-svn] r61846 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090213183201.65D63168578@codespeak.net> Author: getxsick Date: Fri Feb 13 19:31:58 2009 New Revision: 61846 Modified: pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) setlocale() (partial) implementation Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Fri Feb 13 19:31:58 2009 @@ -92,10 +92,13 @@ def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=CConfig._compilation_info_) -def setlocale(space, w_category, w_locale): - pass +_setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP) -setlocale.unwrap_spec = [ObjSpace, W_Root, W_Root] +def setlocale(space, category, locale): + result = _setlocale(rffi.cast(rffi.INT, category), rffi.str2charp(locale)) + return space.wrap(rffi.charp2str(result)) + +setlocale.unwrap_spec = [ObjSpace, int, str] _lconv = lltype.Ptr(cConfig.lconv) _localeconv = external('localeconv', [], _lconv) Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Fri Feb 13 19:31:58 2009 @@ -40,11 +40,11 @@ assert hasattr(_locale, constant) def test_str_float(self): - skip("in progress") + import _locale import locale - locale.setlocale(locale.LC_ALL, "en_US") + _locale.setlocale(_locale.LC_ALL, "en_US") assert locale.str(1.1) == '1.1' - locale.setlocale(locale.LC_ALL, "pl_PL") + _locale.setlocale(_locale.LC_ALL, "pl_PL") assert locale.str(1.1) == '1,1' From fijal at codespeak.net Fri Feb 13 20:13:07 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 20:13:07 +0100 (CET) Subject: [pypy-svn] r61847 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213191307.ED20A168569@codespeak.net> Author: fijal Date: Fri Feb 13 20:13:05 2009 New Revision: 61847 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: A bit of hacking, but overall better than I thought. This way we can detect values that are just passed around and make them delayed. Accidentally rebuilding values work (might be by accident though) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 20:13:05 2009 @@ -5,7 +5,9 @@ from pypy.jit.metainterp.specnode import (FixedClassSpecNode, VirtualInstanceSpecNode, VirtualizableSpecNode, - NotSpecNode) + NotSpecNode, + DelayedSpecNode, + SpecNodeWithBox) from pypy.rlib.objectmodel import we_are_translated class CancelInefficientLoop(Exception): @@ -76,6 +78,7 @@ self.curfields = {} self.cleanfields = {} self.dirtyfields = {} + self.expanded_fields = {} def escape_if_startbox(self, memo): if self in memo: @@ -101,7 +104,8 @@ known_class = self.cls.source else: known_class = other.cls.source - if other.escaped and not other.virtualized: + if (other.escaped and not other.virtualized and + not self.expanded_fields): if self.cls is None: return NotSpecNode() return FixedClassSpecNode(known_class) @@ -117,6 +121,14 @@ specnode = NotSpecNode() fields.append((ofs, specnode)) return VirtualInstanceSpecNode(known_class, fields) + if not other.virtualized and self.expanded_fields: + fields = [] + lst = self.expanded_fields.keys() + lst.sort() + for ofs in lst: + specnode = SpecNodeWithBox(self.origfields[ofs].source) + fields.append((ofs, specnode)) + return DelayedSpecNode(known_class, fields) else: assert self is other d = self.origfields.copy() @@ -196,6 +208,7 @@ def find_nodes(self): # Steps (1) and (2) + first_escaping_op = True for box in self.loop.operations[0].args: self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) @@ -206,6 +219,7 @@ instnode = InstanceNode(box, escaped=False) instnode.cls = InstanceNode(op.args[1]) self.nodes[box] = instnode + first_escaping_op = False continue elif opname == 'setfield_gc': instnode = self.getnode(op.args[0]) @@ -233,6 +247,8 @@ self.dependency_graph.append((instnode, fieldnode)) instnode.origfields[field] = fieldnode self.nodes[box] = fieldnode + if first_escaping_op: + instnode.expanded_fields[field] = None continue elif opname == 'guard_class': instnode = self.getnode(op.args[0]) @@ -249,6 +265,7 @@ elif opname not in ('oois', 'ooisnot', 'ooisnull', 'oononnull'): # default case + first_escaping_op = False for box in op.args: if isinstance(box, Box): self.nodes[box].escaped = True @@ -290,13 +307,14 @@ specnodes.append(enternode.intersect(leavenode)) self.specnodes = specnodes - def expanded_version_of(self, boxlist): + def expanded_version_of(self, boxlist, oplist): + # oplist is None means at the start newboxlist = [] assert len(boxlist) == len(self.specnodes) for i in range(len(boxlist)): box = boxlist[i] specnode = self.specnodes[i] - specnode.expand_boxlist(self.nodes[box], newboxlist) + specnode.expand_boxlist(self.nodes[box], newboxlist, oplist) return newboxlist def optimize_guard(self, op): @@ -367,13 +385,13 @@ for op in self.loop.operations: opname = op.opname if opname == 'merge_point': - args = self.expanded_version_of(op.args) + args = self.expanded_version_of(op.args, None) op = MergePoint('merge_point', args, []) newoperations.append(op) continue elif opname == 'jump': - self.adjust_operations_before_jump(newoperations) - args = self.expanded_version_of(op.args) + args = self.expanded_version_of(op.args, newoperations) + self.cleanup_field_caches(newoperations) op = Jump('jump', args, []) newoperations.append(op) continue @@ -462,6 +480,7 @@ continue elif opname not in operations_without_side_effects: self.cleanup_field_caches(newoperations) + first_escaping_op = False for box in op.results: instnode = InstanceNode(box) self.nodes[box] = instnode @@ -470,7 +489,19 @@ newoperations[0].specnodes = self.specnodes self.loop.operations = newoperations - def adjust_operations_before_jump(self, newoperations): + def adjust_operations_before_jump(self, newoperations, args, newargs): + xxx + xxx + for i in range(len(args)): + specnode = self.specnodes[i] + arg = args[i] + if isinstance(specnode, DelayedSpecNode): + for ofs, subspecnode in specnode.fields: + source = self.nodes[arg].source + if ofs not in self.nodes[arg].cleanfields: + v = subspecnode.box + newoperations.append(ResOperation('getfield_gc', + [source, ConstInt(ofs)], [v])) self.cleanup_field_caches(newoperations) def cleanup_field_caches(self, newoperations): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Fri Feb 13 20:13:05 2009 @@ -3,14 +3,14 @@ class SpecNode(object): - def expand_boxlist(self, instnode, newboxlist): + def expand_boxlist(self, instnode, newboxlist, start): newboxlist.append(instnode.source) def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) def adapt_to(self, instnode): - instnode.escaped = True + instnode.escaped = True class NotSpecNode(SpecNode): def mutate_nodes(self, instnode): @@ -25,6 +25,15 @@ # NotSpecNode matches everything return True +class SpecNodeWithBox(NotSpecNode): + def __init__(self, box): + self.box = box + + def equals(self, other): + if type(other) is SpecNodeWithBox: + return True + return False + class FixedClassSpecNode(SpecNode): def __init__(self, known_class): self.known_class = known_class @@ -90,10 +99,10 @@ return False return True - def expand_boxlist(self, instnode, newboxlist): + def expand_boxlist(self, instnode, newboxlist, start): for ofs, subspecnode in self.fields: subinstnode = instnode.curfields[ofs] # should really be there - subspecnode.expand_boxlist(subinstnode, newboxlist) + subspecnode.expand_boxlist(subinstnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): for ofs, subspecnode in self.fields: @@ -108,16 +117,11 @@ for ofs, subspecnode in self.fields: subspecnode.adapt_to(instnode.curfields[ofs]) -class VirtualizableSpecNode(SpecNodeWithFields): +class VirtualizedSpecNode(SpecNodeWithFields): - def equals(self, other): - if not isinstance(other, VirtualizableSpecNode): - return False - return SpecNodeWithFields.equals(self, other) - - def expand_boxlist(self, instnode, newboxlist): - newboxlist.append(instnode.source) - SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist) + def expand_boxlist(self, instnode, newboxlist, start): + newboxlist.append(instnode.source) + SpecNodeWithFields.expand_boxlist(self, instnode, newboxlist, start) def extract_runtime_data(self, cpu, valuebox, resultlist): resultlist.append(valuebox) @@ -127,6 +131,33 @@ instnode.escaped = True SpecNodeWithFields.adapt_to(self, instnode) +class DelayedSpecNode(VirtualizedSpecNode): + + def expand_boxlist(self, instnode, newboxlist, oplist): + from pypy.jit.metainterp.history import ResOperation, ConstInt + + newboxlist.append(instnode.source) + for ofs, subspecnode in self.fields: + assert isinstance(subspecnode, SpecNodeWithBox) + if oplist is None: + instnode.cleanfields[ofs] = instnode.origfields[ofs] + newboxlist.append(instnode.curfields[ofs].source) + else: + if ofs in instnode.cleanfields: + newboxlist.append(instnode.cleanfields[ofs].source) + else: + box = subspecnode.box.clonebox() + oplist.append(ResOperation('getfield_gc', + [instnode.source, ConstInt(ofs)], [box])) + newboxlist.append(box) + +class VirtualizableSpecNode(VirtualizedSpecNode): + + def equals(self, other): + if not isinstance(other, VirtualizableSpecNode): + return False + return SpecNodeWithFields.equals(self, other) + class VirtualInstanceSpecNode(SpecNodeWithFields): def mutate_nodes(self, instnode): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 20:13:05 2009 @@ -195,6 +195,7 @@ ops = [ MergePoint('merge_point', [sum, n1], []), ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('some_escaping_operation', [n1], []), # <== escaping ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -231,6 +232,7 @@ equaloplists(spec.loop.operations, [ MergePoint('merge_point', [C.sum, C.n1], []), # guard_class is gone + ResOperation('some_escaping_operation', [C.n1], []), # <== escaping ResOperation('getfield_gc', [C.n1, ConstInt(C.ofs_value)], [C.v]), ResOperation('int_sub', [C.v, ConstInt(1)], [C.v2]), ResOperation('int_add', [C.sum, C.v], [C.sum2]), @@ -545,13 +547,13 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [K0.sum, K0.n1], []), - ResOperation('getfield_gc', [K0.n1, ConstInt(K0.ofs_value)], [K0.v]), + MergePoint('merge_point', [K0.sum, K0.n1, K0.v], []), ResOperation('int_sub', [K0.v, ConstInt(1)], [K0.v2]), ResOperation('int_add', [K0.sum, K0.v], [K0.sum2]), ResOperation('int_add', [K0.sum2, K0.v], [K0.sum3]), ResOperation('escape', [K0.n1], []), - Jump('jump', [K0.sum3, K0.n1], []), + ResOperation('getfield_gc', [K0.n1, ConstInt(K0.ofs_value)], [ANY]), + Jump('jump', [K0.sum3, K0.n1, ANY], []), ]) @@ -578,15 +580,15 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [K1.sum, K1.n1], []), - ResOperation('getfield_gc', [K1.n1, ConstInt(K1.ofs_value)], [K1.v]), + MergePoint('merge_point', [K1.sum, K1.n1, K1.v], []), ResOperation('int_sub', [K1.v, ConstInt(1)], [K1.v2]), ResOperation('int_add', [K1.sum, K1.v], [K1.sum2]), ResOperation('int_add', [K1.sum2, K1.sum], [K1.sum3]), ResOperation('setfield_gc', [K1.n1, ConstInt(K1.ofs_value), K1.sum], []), ResOperation('escape', [K1.n1], []), - Jump('jump', [K1.sum3, K1.n1], []), + ResOperation('getfield_gc', [K1.n1, ConstInt(K1.ofs_value)], [ANY]), + Jump('jump', [K1.sum3, K1.n1, ANY], []), ]) @@ -606,7 +608,6 @@ ] def test_K_optimize_loop(): - py.test.skip("not yet") spec = PerfectSpecializer(Loop(K.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -638,7 +639,6 @@ ] def test_L_optimize_loop(): - py.test.skip("not yet") spec = PerfectSpecializer(Loop(L.ops)) spec.find_nodes() spec.intersect_input_and_output() @@ -648,11 +648,10 @@ ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), ResOperation('int_add', [L.sum, L.v], [L.sum2]), ResOperation('escape', [L.n1], []), - ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v3]), + ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], [L.v3]), ResOperation('int_add', [L.sum2, L.v3], [L.sum3]), Jump('jump', [L.sum3, L.n1, L.v3], []), ]) - assert spec.loop.prologue == [(L.n1, L.v, L.ofs_value)] # ____________________________________________________________ @@ -671,18 +670,17 @@ ] def test_M_optimize_loop(): - py.test.skip("not yet") - spec = PerfectSpecializer(Loop(L.ops)) + spec = PerfectSpecializer(Loop(M.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [L.sum, L.n1], []), - ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], [L.v]), + MergePoint('merge_point', [L.sum, L.n1, L.v], []), ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), ResOperation('int_add', [L.sum, L.v], [L.sum2]), ResOperation('escape', [L.n1], []), - Jump('jump', [L.sum2, L.n1], []), + ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], [ANY]), + Jump('jump', [L.sum2, L.n1, ANY], []), ]) - assert spec.loop.prologue == [] + From antocuni at codespeak.net Fri Feb 13 20:32:49 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 13 Feb 2009 20:32:49 +0100 (CET) Subject: [pypy-svn] r61848 - in pypy/branch/oo-jit/pypy: jit/codegen/i386 module/pypyjit translator/cli translator/goal Message-ID: <20090213193249.0230F16856B@codespeak.net> Author: antocuni Date: Fri Feb 13 20:32:47 2009 New Revision: 61848 Modified: pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py pypy/branch/oo-jit/pypy/module/pypyjit/__init__.py pypy/branch/oo-jit/pypy/module/pypyjit/interp_jit.py pypy/branch/oo-jit/pypy/module/pypyjit/newbool.py pypy/branch/oo-jit/pypy/module/pypyjit/portal.py pypy/branch/oo-jit/pypy/translator/cli/opcodes.py pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py Log: tentative checkin: try to revert the pypy hint to the pre-hotpath state. Probably broken, I check in this so that I can try a translation somewhere else Modified: pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py Fri Feb 13 20:32:47 2009 @@ -1,5 +1,5 @@ from pypy.rlib.rarithmetic import intmask -from pypy.rlib.objectmodel import ComputedIntSymbolic +from pypy.rlib.objectmodel import ComputedIntSymbolic, CDefinedIntSymbolic class OPERAND(object): _attrs_ = [] @@ -246,6 +246,8 @@ def imm(value): if isinstance(value, ComputedIntSymbolic): value = value.compute_fn() + elif isinstance(value, CDefinedIntSymbolic): + raise TypeError # XXX? assert isinstance(value, int) if single_byte(value): return imm8(value) Modified: pypy/branch/oo-jit/pypy/module/pypyjit/__init__.py ============================================================================== --- pypy/branch/oo-jit/pypy/module/pypyjit/__init__.py (original) +++ pypy/branch/oo-jit/pypy/module/pypyjit/__init__.py Fri Feb 13 20:32:47 2009 @@ -5,9 +5,9 @@ } interpleveldefs = { - 'set_param': 'interp_jit.set_param', + 'enable': 'interp_jit.enable', } def setup_after_space_initialization(self): - # force the __extend__ hacks to occur early + # force the setup() to run early import pypy.module.pypyjit.interp_jit Modified: pypy/branch/oo-jit/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/oo-jit/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/oo-jit/pypy/module/pypyjit/interp_jit.py Fri Feb 13 20:32:47 2009 @@ -1,15 +1,17 @@ """This is not the JIT :-) -This is transformed to become a JIT by code elsewhere: pypy/jit/* +The pypyjit module helpers set the 'jit_enable' flag on code objects. +The code below makes two identical copies of the interpreter's main +loop, and the flag controls which of them is used. One of them +(dispatch_jit) is transformed to become a JIT by code elsewhere: +pypy/jit/* """ import py import sys from pypy.tool.pairtype import extendabletype from pypy.rlib.rarithmetic import r_uint, intmask -from pypy.rlib.jit import hint, _is_early_constant, JitDriver +from pypy.rlib.jit import hint, _is_early_constant import pypy.interpreter.pyopcode # for side-effects -from pypy.interpreter.error import OperationError -from pypy.interpreter.gateway import ObjSpace, Arguments from pypy.interpreter.eval import Frame from pypy.interpreter.pycode import PyCode, CO_VARARGS, CO_VARKEYWORDS from pypy.interpreter.pyframe import PyFrame @@ -21,76 +23,110 @@ PyCode.jit_enable = False # new default attribute super_dispatch = PyFrame.dispatch -class PyPyJitDriver(JitDriver): - reds = ['frame', 'ec'] - greens = ['next_instr', 'pycode'] - - def compute_invariants(self, reds, next_instr, pycode): - # compute the information that really only depends on next_instr - # and pycode - frame = reds.frame - valuestackdepth = frame.valuestackdepth - blockstack = frame.blockstack - return (valuestackdepth, blockstack) +class __extend__(PyFrame): - def on_enter_jit(self, invariants, reds, next_instr, pycode): - # *loads* of nonsense for now - (depth, oldblockstack) = invariants - frame = reds.frame + def dispatch(self, pycode, next_instr, ec): + if pycode.jit_enable: + return self.dispatch_jit(pycode, next_instr, ec) + else: + self = hint(self, access_directly=True) + return super_dispatch(self, pycode, next_instr, ec) + + def dispatch_jit(self, pycode, next_instr, ec): + hint(None, global_merge_point=True) pycode = hint(pycode, deepfreeze=True) + entry_fastlocals_w = self.jit_enter_frame(pycode, next_instr) + + # For the sequel, force 'next_instr' to be unsigned for performance + next_instr = r_uint(next_instr) + co_code = pycode.co_code + + try: + try: + while True: + hint(None, global_merge_point=True) + next_instr = self.handle_bytecode(co_code, next_instr, ec) + except Return: + w_result = self.popvalue() + self.blockstack = None + self.valuestack_w = None + return w_result + except Yield: + w_result = self.popvalue() + return w_result + finally: + self.jit_leave_frame(pycode, entry_fastlocals_w) + + def jit_enter_frame(self, pycode, next_instr): + # *loads* of nonsense for now + fastlocals_w = [None] * pycode.co_nlocals - i = pycode.co_nlocals - while True: - i -= 1 - if i < 0: - break - hint(i, concrete=True) - w_obj = frame.fastlocals_w[i] - fastlocals_w[i] = w_obj + if next_instr == 0: + # first time we enter this function + depth = 0 + self.blockstack = [] + + numargs = pycode.co_argcount + if pycode.co_flags & CO_VARARGS: numargs += 1 + if pycode.co_flags & CO_VARKEYWORDS: numargs += 1 + while True: + numargs -= 1 + if numargs < 0: + break + hint(numargs, concrete=True) + w_obj = self.fastlocals_w[numargs] + assert w_obj is not None + fastlocals_w[numargs] = w_obj - frame.pycode = pycode - frame.valuestackdepth = depth + else: + stuff = self.valuestackdepth + if len(self.blockstack): + stuff |= (-sys.maxint-1) + + stuff = hint(stuff, promote=True) + if stuff >= 0: + # blockdepth == 0, common case + self.blockstack = [] + depth = stuff & sys.maxint - frame.fastlocals_w = fastlocals_w + i = pycode.co_nlocals + while True: + i -= 1 + if i < 0: + break + hint(i, concrete=True) + w_obj = self.fastlocals_w[i] + fastlocals_w[i] = w_obj + + self.pycode = pycode + self.valuestackdepth = depth + + entry_fastlocals_w = self.fastlocals_w + self.fastlocals_w = fastlocals_w virtualstack_w = [None] * pycode.co_stacksize while depth > 0: depth -= 1 hint(depth, concrete=True) - virtualstack_w[depth] = frame.valuestack_w[depth] - frame.valuestack_w = virtualstack_w + virtualstack_w[depth] = self.valuestack_w[depth] + self.valuestack_w = virtualstack_w + return entry_fastlocals_w - # XXX we should also make a completely virtual copy of oldblockstack + def jit_leave_frame(self, pycode, entry_fastlocals_w): + i = pycode.co_nlocals + while True: + i -= 1 + if i < 0: + break + hint(i, concrete=True) + entry_fastlocals_w[i] = self.fastlocals_w[i] -pypyjitdriver = PyPyJitDriver() + self.fastlocals_w = entry_fastlocals_w -class __extend__(PyFrame): - def dispatch(self, pycode, next_instr, ec): - next_instr = r_uint(next_instr) - try: - while True: - pypyjitdriver.jit_merge_point( - frame=self, ec=ec, next_instr=next_instr, pycode=pycode) - pycode = hint(pycode, deepfreeze=True) - co_code = pycode.co_code - next_instr = self.handle_bytecode(co_code, next_instr, ec) - except Return: - w_result = self.popvalue() - self.blockstack = None - self.valuestack_w = None - return w_result - except Yield: - w_result = self.popvalue() - return w_result - - def JUMP_ABSOLUTE(f, jumpto, next_instr, *ignored): - ec = f.space.getexecutioncontext() - pypyjitdriver.can_enter_jit(frame=f, ec=ec, next_instr=jumpto, - pycode=f.getcode()) - return jumpto +PORTAL = PyFrame.dispatch_jit class __extend__(Function): __metaclass__ = extendabletype @@ -111,46 +147,15 @@ # # Public interface -def jit_startup(space, argv): +def enable(space, w_code, w_enabled=True): # save the app-level sys.executable in JITInfo, where the machine - # code backend can fish for it. A bit hackish. + # code backend can fish for it - XXX the following import will look + # less obscure once codebuf.py is moved to a general + # processor-independent place from pypy.jit.codegen.hlinfo import highleveljitinfo - highleveljitinfo.sys_executable = argv[0] - - # recognize the option --jit PARAM=VALUE,PARAM=VALUE... - # if it is at the beginning. A bit ad-hoc. - if len(argv) > 2 and argv[1] == '--jit': - argv.pop(1) - try: - pypyjitdriver.set_user_param(argv.pop(1)) - except ValueError: - from pypy.rlib.debug import debug_print - debug_print("WARNING: invalid --jit parameters string") - - -def set_param(space, args): - '''Configure the tunable JIT parameters. - * set_param(name=value, ...) # as keyword arguments - * set_param("name=value,name=value") # as a user-supplied string - ''' - args_w, kwds_w = args.unpack() - if len(args_w) > 1: - msg = ("set_param() takes at most 1 non-keyword argument, %d given" - % len(args_w)) - raise OperationError(space.w_TypeError, space.wrap(msg)) - if len(args_w) == 1: - text = space.str_w(args_w[0]) - try: - pypyjitdriver.set_user_param(text) - except ValueError: - raise OperationError(space.w_ValueError, - space.wrap("error in JIT parameters string")) - for key, w_value in kwds_w.items(): - intval = space.int_w(w_value) - try: - pypyjitdriver.set_param(key, intval) - except ValueError: - raise OperationError(space.w_TypeError, - space.wrap("no JIT parameter '%s'" % (key,))) + if highleveljitinfo.sys_executable is None: + highleveljitinfo.sys_executable = space.str_w( + space.sys.get('executable')) -set_param.unwrap_spec = [ObjSpace, Arguments] + code = space.interp_w(PyCode, w_code) + code.jit_enable = space.is_true(w_enabled) Modified: pypy/branch/oo-jit/pypy/module/pypyjit/newbool.py ============================================================================== --- pypy/branch/oo-jit/pypy/module/pypyjit/newbool.py (original) +++ pypy/branch/oo-jit/pypy/module/pypyjit/newbool.py Fri Feb 13 20:32:47 2009 @@ -62,7 +62,8 @@ else: if reverse: gv_bool = jitstate.curbuilder.genop1("bool_not", gv_bool) - return rvalue.IntRedBox(self.boolkind, gv_bool) + #return rvalue.IntRedBox(self.boolkind, gv_bool) + return rvalue.IntRedBox(gv_bool) def genbooleq(self, jitstate, gv_bool1, gv_bool2, reverse=False): if gv_bool1.is_const: @@ -80,6 +81,7 @@ gv_res = curbuilder.genop2("int_ne", gv_int1, gv_int2) else: gv_res = curbuilder.genop2("int_eq", gv_int1, gv_int2) + #return rvalue.IntRedBox(self.boolkind, gv_res) return rvalue.IntRedBox(self.boolkind, gv_res) Modified: pypy/branch/oo-jit/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/oo-jit/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/oo-jit/pypy/module/pypyjit/portal.py Fri Feb 13 20:32:47 2009 @@ -1,11 +1,12 @@ import pypy -#from pypy.module.pypyjit.newbool import NewBoolDesc +from pypy.module.pypyjit.interp_jit import PORTAL +from pypy.module.pypyjit.newbool import NewBoolDesc from pypy.translator.translator import graphof from pypy.annotation.specialize import getuniquenondirectgraph from pypy.jit.hintannotator.policy import ManualGraphPolicy class PyPyHintAnnotatorPolicy(ManualGraphPolicy): - hotpath = True + PORTAL = PORTAL def look_inside_graph_of_module(self, graph, func, mod): if mod.startswith('pypy.objspace'): @@ -101,7 +102,7 @@ self.seegraph(pypy.interpreter.pyframe.PyFrame.execute_frame, False) # -------------------- # special timeshifting logic for newbool - #self.seegraph(pypy.objspace.std.Space.newbool, NewBoolDesc) + self.seegraph(pypy.objspace.std.Space.newbool, NewBoolDesc) self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, pypy.objspace.std.Space.is_true) self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, @@ -126,6 +127,9 @@ def get_portal(drv): t = drv.translator + portal = getattr(PORTAL, 'im_func', PORTAL) + portal_graph = graphof(t, portal) + policy = PyPyHintAnnotatorPolicy() policy.seetranslator(t) - return None, policy + return portal, policy Modified: pypy/branch/oo-jit/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/opcodes.py Fri Feb 13 20:32:47 2009 @@ -106,6 +106,7 @@ 'ullong_is_true': [PushAllArgs, 'ldc.i8 0', 'cgt.un'], 'ullong_invert': 'not', + # XXX: why nop nop nop? 'ooisnull': [PushAllArgs, 'nop', 'nop', 'nop', 'ldnull', 'ceq'], 'oononnull': [PushAllArgs, 'nop', 'nop', 'nop', 'nop', 'ldnull', 'ceq']+Not, Modified: pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/oo-jit/pypy/translator/goal/targetpypystandalone.py Fri Feb 13 20:32:47 2009 @@ -47,12 +47,12 @@ try: space.call_function(w_run_toplevel, w_call_startup_gateway) - if space.config.objspace.usemodules.pypyjit: - # initial setup of the JIT and handling of the - # '--jit PARAM=VALUE,PARAM=VALUE...' command-line option - # (for now it's a bit ad-hoc) - from pypy.module.pypyjit.interp_jit import jit_startup - jit_startup(space, argv) +## if space.config.objspace.usemodules.pypyjit: +## # initial setup of the JIT and handling of the +## # '--jit PARAM=VALUE,PARAM=VALUE...' command-line option +## # (for now it's a bit ad-hoc) +## from pypy.module.pypyjit.interp_jit import jit_startup +## jit_startup(space, argv) w_executable = space.wrap(argv[0]) w_argv = space.newlist([space.wrap(s) for s in argv[1:]]) From jlg at codespeak.net Fri Feb 13 20:49:48 2009 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 13 Feb 2009 20:49:48 +0100 (CET) Subject: [pypy-svn] r61849 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090213194948.6FEC8168570@codespeak.net> Author: jlg Date: Fri Feb 13 20:49:46 2009 New Revision: 61849 Modified: pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (getxsick, jlg) setlocal() fully implemented Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Fri Feb 13 20:49:46 2009 @@ -4,10 +4,7 @@ """Support for POSIX locales.""" interpleveldefs = { - #'Error': 'interp_locale.Error', - #'LocalConfigure': 'interp_locale.LocaleConfigure', #'lconv': 'interp_locale.lconv', - #'fixup_ulcase': 'interp_locale.fixup_ulcase', 'setlocale': 'interp_locale.setlocale', 'localeconv': 'interp_locale.localeconv', #'strcoll': 'interp_locale.strcoll', @@ -17,6 +14,8 @@ } appleveldefs = { + 'Error': 'app_locale.Error', + '_fixup_ulcase': 'app_locale._fixup_ulcase', } def buildloaders(cls): Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Fri Feb 13 20:49:46 2009 @@ -1,7 +1,8 @@ from pypy.rpython.tool import rffi_platform as platform from pypy.rpython.lltypesystem import rffi, lltype -from pypy.interpreter.gateway import interp2app, ObjSpace, W_Root +from pypy.interpreter.error import OperationError +from pypy.interpreter.gateway import ObjSpace, W_Root from pypy.translator.tool.cbuild import ExternalCompilationInfo @@ -92,13 +93,37 @@ def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=CConfig._compilation_info_) +def make_error(space, msg): + w_module = space.getbuiltinmodule('_locale') + w_exception_class = space.getattr(w_module, space.wrap('Error')) + w_exception = space.call_function(w_exception_class, space.wrap(msg)) + return OperationError(w_exception_class, w_exception) + _setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP) -def setlocale(space, category, locale): - result = _setlocale(rffi.cast(rffi.INT, category), rffi.str2charp(locale)) +def setlocale(space, category, w_locale=None): + if space.is_w(w_locale, space.w_None) or w_locale is None: + + result = _setlocale(rffi.cast(rffi.INT, category), None) + if not result: + raise make_error(space, "locale query failed") + + else: + locale = rffi.str2charp(space.str_w(w_locale)) + + result = _setlocale(rffi.cast(rffi.INT, category), locale) + if not result: + raise make_error(space, "unsupported locale setting") + + # record changes to LC_CTYPE + if category in (LC_CTYPE, LC_ALL): + w_module = space.getbuiltinmodule('_locale') + w_fun = space.getattr(w_module, space.wrap('_fixup_ulcase')) + space.call_function(w_fun) + return space.wrap(rffi.charp2str(result)) -setlocale.unwrap_spec = [ObjSpace, int, str] +setlocale.unwrap_spec = [ObjSpace, int, W_Root] _lconv = lltype.Ptr(cConfig.lconv) _localeconv = external('localeconv', [], _lconv) Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Fri Feb 13 20:49:46 2009 @@ -39,6 +39,30 @@ for constant in _CONSTANTS: assert hasattr(_locale, constant) + def test_setlocale(self): + import _locale + + raises(TypeError, _locale.setlocale, "", "en_US") + raises(TypeError, _locale.setlocale, _locale.LC_ALL, 6) + raises(_locale.Error, _locale.setlocale, 123456, "en_US") + + assert _locale.setlocale(_locale.LC_ALL, None) + assert _locale.setlocale(_locale.LC_ALL) + + def test_string_ulcase(self): + import _locale, string + + lcase = "abcdefghijklmnopqrstuvwxyz" + ucase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + _locale.setlocale(_locale.LC_ALL, "en_US.UTF-8") + assert string.lowercase == lcase + assert string.uppercase == ucase + + _locale.setlocale(_locale.LC_ALL, "en_US") + assert string.lowercase != lcase + assert string.uppercase != ucase + def test_str_float(self): import _locale import locale From jlg at codespeak.net Fri Feb 13 20:50:35 2009 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 13 Feb 2009 20:50:35 +0100 (CET) Subject: [pypy-svn] r61850 - pypy/trunk/pypy/module/_locale Message-ID: <20090213195035.687C116856E@codespeak.net> Author: jlg Date: Fri Feb 13 20:50:34 2009 New Revision: 61850 Added: pypy/trunk/pypy/module/_locale/app_locale.py Log: (getxsick, jlg) forgoten file Added: pypy/trunk/pypy/module/_locale/app_locale.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/_locale/app_locale.py Fri Feb 13 20:50:34 2009 @@ -0,0 +1,34 @@ + +class Error(Exception): + pass + +def _fixup_ulcase(): + import string + + # create uppercase map string + ul = [] + for c in xrange(256): + c = chr(c) + if c.isupper(): + ul.append(c) + ul = ''.join(ul) + string.uppercase = ul + + # create lowercase string + ul = [] + for c in xrange(256): + c = chr(c) + if c.islower(): + ul.append(c) + ul = ''.join(ul) + string.lowercase = ul + + # create letters string + ul = [] + for c in xrange(256): + c = chr(c) + if c.isalpha(): + ul.append(c) + ul = ''.join(ul) + string.letters = ul + From getxsick at codespeak.net Fri Feb 13 20:57:27 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Fri, 13 Feb 2009 20:57:27 +0100 (CET) Subject: [pypy-svn] r61851 - pypy/trunk/pypy/module/_locale Message-ID: <20090213195727.B0903168573@codespeak.net> Author: getxsick Date: Fri Feb 13 20:57:27 2009 New Revision: 61851 Modified: pypy/trunk/pypy/module/_locale/interp_locale.py Log: (jlg, getxsick) docstrings for setlocale() aka yet another forgotten thing Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Fri Feb 13 20:57:27 2009 @@ -102,12 +102,12 @@ _setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP) def setlocale(space, category, w_locale=None): - if space.is_w(w_locale, space.w_None) or w_locale is None: + "(integer,string=None) -> string. Activates/queries locale processing." + if space.is_w(w_locale, space.w_None) or w_locale is None: result = _setlocale(rffi.cast(rffi.INT, category), None) if not result: raise make_error(space, "locale query failed") - else: locale = rffi.str2charp(space.str_w(w_locale)) From fijal at codespeak.net Fri Feb 13 21:49:55 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 21:49:55 +0100 (CET) Subject: [pypy-svn] r61852 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090213204955.EAA2D16855E@codespeak.net> Author: fijal Date: Fri Feb 13 21:49:53 2009 New Revision: 61852 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: A bit break everything. In particular * Introduce guard_builtin that helps keeping in mind that we know the class. We likely want to just insert such guard_builtin for lists. * Propagate getitem/setitem through pyjitpl in order to know that we're operating on lists * Actually use the same machinery as for virtuals for virtual lists. not yet completely working Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Feb 13 21:49:53 2009 @@ -510,6 +510,16 @@ self.emit('jit_merge_point') assert ([self.var_position(i) for i in op.args[2:]] == range(0, 2*(len(op.args) - 2), 2)) + for i in range(2, len(op.args)): + arg = op.args[i] + if isinstance(arg.concretetype, lltype.Ptr): + # XXX very complex logic for getting all things + # that are pointers, but not objects + if not (isinstance(arg.concretetype.TO, lltype.GcStruct) and + (heaptracker.get_vtable_for_gcstruct(self.cpu, + arg.concretetype.TO))): + self.emit('guard_builtin', self.var_position(arg)) + elif op.args[0].value == 'can_enter_jit': self.emit('can_enter_jit') self.emit_varargs(op.args[2:]) @@ -568,6 +578,10 @@ opname = 'green_call_%s' else: opname = 'residual_call_%s' + if oopspec_name == 'list.getitem': + opname = 'getitem_%s' + if oopspec_name == 'list.setitem': + opname = 'setitem_%s' self.emit(opname % getkind_num(self.cpu, op.result.concretetype)) self.emit_varargs([c_func] + args) self.register_var(op.result) @@ -610,7 +624,6 @@ if x.concretetype is not lltype.Void]) self.register_var(op.result) - def serialize_op_debug_assert(self, op): pass # for now Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Fri Feb 13 21:49:53 2009 @@ -80,4 +80,9 @@ operations_without_side_effects = {} always_pure_operations = {} + +for guard in ['guard_no_exception', 'guard_exception', 'guard_true', + 'guard_false', 'guard_value', 'guard_class']: + always_pure_operations[guard] = True + setup() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 21:49:53 2009 @@ -1,4 +1,4 @@ -from pypy.jit.metainterp.history import (Box, Const, ConstInt, +from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, MergePoint, ResOperation, Jump) from pypy.jit.metainterp.heaptracker import (always_pure_operations, operations_without_side_effects) @@ -206,9 +206,28 @@ node = self.nodes[box] = InstanceNode(box, escaped=True) return node + def find_nodes_setfield(self, instnode, ofs, fieldnode): + instnode.curfields[ofs] = fieldnode + self.dependency_graph.append((instnode, fieldnode)) + + def find_nodes_getfield(self, instnode, field, box): + if field in instnode.curfields: + fieldnode = instnode.curfields[field] + elif field in instnode.origfields: + fieldnode = instnode.origfields[field] + else: + fieldnode = InstanceNode(box, escaped=False) + if instnode.startbox: + fieldnode.startbox = True + self.dependency_graph.append((instnode, fieldnode)) + instnode.origfields[field] = fieldnode + self.nodes[box] = fieldnode + if self.first_escaping_op: + instnode.expanded_fields[field] = None + def find_nodes(self): # Steps (1) and (2) - first_escaping_op = True + self.first_escaping_op = True for box in self.loop.operations[0].args: self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) @@ -219,16 +238,20 @@ instnode = InstanceNode(box, escaped=False) instnode.cls = InstanceNode(op.args[1]) self.nodes[box] = instnode - first_escaping_op = False + self.first_escaping_op = False + continue + elif opname == 'guard_builtin': + instnode = self.nodes[op.args[0]] + # all builtins have equal classes + instnode.cls = InstanceNode(ConstInt(0)) continue elif opname == 'setfield_gc': instnode = self.getnode(op.args[0]) fieldbox = op.args[1] assert isinstance(fieldbox, ConstInt) field = fieldbox.getint() - fieldnode = self.getnode(op.args[2]) - instnode.curfields[field] = fieldnode - self.dependency_graph.append((instnode, fieldnode)) + self.find_nodes_setfield(instnode, field, + self.getnode(op.args[2])) continue elif opname == 'getfield_gc': instnode = self.getnode(op.args[0]) @@ -236,20 +259,24 @@ assert isinstance(fieldbox, ConstInt) field = fieldbox.getint() box = op.results[0] - if field in instnode.curfields: - fieldnode = instnode.curfields[field] - elif field in instnode.origfields: - fieldnode = instnode.origfields[field] - else: - fieldnode = InstanceNode(box, escaped=False) - if instnode.startbox: - fieldnode.startbox = True - self.dependency_graph.append((instnode, fieldnode)) - instnode.origfields[field] = fieldnode - self.nodes[box] = fieldnode - if first_escaping_op: - instnode.expanded_fields[field] = None + self.find_nodes_getfield(instnode, field, box) continue + elif opname == 'getitem': + instnode = self.getnode(op.args[1]) + fieldbox = op.args[2] + if isinstance(fieldbox, ConstInt): + field = fieldbox.getint() + box = op.results[0] + self.find_nodes_getfield(instnode, field, box) + continue + elif opname == 'setitem': + instnode = self.getnode(op.args[1]) + fieldbox = op.args[2] + if isinstance(fieldbox, ConstInt): + field = fieldbox.getint() + self.find_nodes_setfield(instnode, field, + self.getnode(op.args[3])) + continue elif opname == 'guard_class': instnode = self.getnode(op.args[0]) if instnode.cls is None: @@ -262,10 +289,10 @@ if instnode.cls is None: instnode.cls = InstanceNode(op.args[1]) continue - elif opname not in ('oois', 'ooisnot', - 'ooisnull', 'oononnull'): + elif (opname not in always_pure_operations and + opname not in operations_without_side_effects): # default case - first_escaping_op = False + self.first_escaping_op = False for box in op.args: if isinstance(box, Box): self.nodes[box].escaped = True @@ -368,6 +395,26 @@ op.args = self.new_arguments(op) return op + def optimize_getfield(self, instnode, ofs, box): + if instnode.virtual or instnode.virtualized: + assert ofs in instnode.curfields # xxx + self.nodes[box] = instnode.curfields[ofs] + elif ofs in instnode.cleanfields: + self.nodes[box] = instnode.cleanfields[ofs] + else: + instnode.cleanfields[ofs] = InstanceNode(box) + return False + return True + + def optimize_setfield(self, instnode, ofs, valuenode, valuebox): + if instnode.virtual or instnode.virtualized: + instnode.curfields[ofs] = valuenode + else: + assert not valuenode.virtual + instnode.cleanfields[ofs] = self.nodes[valuebox] + instnode.dirtyfields[ofs] = self.nodes[valuebox] + # we never perform this operation here, note + def optimize_loop(self): newoperations = [] mp = self.loop.operations[0] @@ -403,6 +450,8 @@ op = self.optimize_guard(op) newoperations.append(op) continue + elif opname == 'guard_builtin': + continue elif opname == 'guard_nonvirtualized': instnode = self.nodes[op.args[0]] if instnode.virtualized: @@ -420,15 +469,15 @@ elif opname == 'getfield_gc': instnode = self.nodes[op.args[0]] ofs = op.args[1].getint() - if instnode.virtual or instnode.virtualized: - assert ofs in instnode.curfields # xxx - self.nodes[op.results[0]] = instnode.curfields[ofs] + if self.optimize_getfield(instnode, ofs, op.results[0]): continue - elif ofs in instnode.cleanfields: - self.nodes[op.results[0]] = instnode.cleanfields[ofs] - continue - else: - instnode.cleanfields[ofs] = InstanceNode(op.results[0]) + elif opname == 'getitem': + instnode = self.nodes[op.args[1]] + ofsbox = op.args[2] + if isinstance(ofsbox, ConstInt): + ofs = ofsbox.getint() + if self.optimize_getfield(instnode, ofs, op.results[0]): + continue elif opname == 'new_with_vtable': # self.nodes[op.results[0]] keep the value from Steps (1,2) instnode = self.nodes[op.results[0]] @@ -443,14 +492,16 @@ instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] ofs = op.args[1].getint() - if instnode.virtual or instnode.virtualized: - instnode.curfields[ofs] = valuenode - else: - assert not valuenode.virtual - instnode.cleanfields[ofs] = self.nodes[op.args[2]] - instnode.dirtyfields[ofs] = self.nodes[op.args[2]] - # we never perform this operation here, note + self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) continue + elif opname == 'setitem': + instnode = self.nodes[op.args[1]] + valuenode = self.getnode(op.args[3]) + ofsbox = op.args[2] + if isinstance(ofsbox, ConstInt): + ofs = ofsbox.getint() + self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) + continue elif opname == 'ooisnull' or opname == 'oononnull': instnode = self.nodes[op.args[0]] if instnode.virtual: @@ -480,7 +531,6 @@ continue elif opname not in operations_without_side_effects: self.cleanup_field_caches(newoperations) - first_escaping_op = False for box in op.results: instnode = InstanceNode(box) self.nodes[box] = instnode @@ -489,21 +539,6 @@ newoperations[0].specnodes = self.specnodes self.loop.operations = newoperations - def adjust_operations_before_jump(self, newoperations, args, newargs): - xxx - xxx - for i in range(len(args)): - specnode = self.specnodes[i] - arg = args[i] - if isinstance(specnode, DelayedSpecNode): - for ofs, subspecnode in specnode.fields: - source = self.nodes[arg].source - if ofs not in self.nodes[arg].cleanfields: - v = subspecnode.box - newoperations.append(ResOperation('getfield_gc', - [source, ConstInt(ofs)], [v])) - self.cleanup_field_caches(newoperations) - def cleanup_field_caches(self, newoperations): # we need to invalidate everything for node in self.nodes.values(): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Feb 13 21:49:53 2009 @@ -375,6 +375,14 @@ def opimpl_residual_call_void(self, varargs): return self.execute_with_exc('call_void', varargs, 'void') + @arguments("varargs") + def opimpl_getitem__4(self, varargs): + return self.execute_with_exc('getitem', varargs, 'int') + + @arguments("varargs") + def opimpl_setitem_void(self, varargs): + return self.execute_with_exc('setitem', varargs, 'void') + @arguments("indirectcallset", "box", "varargs") def opimpl_indirect_call(self, indirectcallset, box, varargs): assert isinstance(box, Const) # XXX @@ -411,6 +419,10 @@ self.generate_guard(pc, 'guard_class', box, [clsbox]) return clsbox + @arguments("orgpc", "box") + def opimpl_guard_builtin(self, pc, box): + self.generate_guard(pc, "guard_builtin", box) + @arguments("orgpc", "box", "virtualizabledesc", "int") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): clsbox = self.cls_of_box(box) From jlg at codespeak.net Fri Feb 13 21:59:10 2009 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 13 Feb 2009 21:59:10 +0100 (CET) Subject: [pypy-svn] r61853 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090213205910.F241816855F@codespeak.net> Author: jlg Date: Fri Feb 13 21:59:10 2009 New Revision: 61853 Modified: pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (getxsick, jlg) localeconv() implemented, but test_localeconv raises BytecodeCorruption Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Fri Feb 13 21:59:10 2009 @@ -35,15 +35,15 @@ ("negative_sign", rffi.CCHARP), # Sign for negative values. ("int_frac_digits", rffi.UCHAR), # Int'l fractional digits. - ("frac_digits", rffi.CHAR), # Local fractional digits. + ("frac_digits", rffi.UCHAR), # Local fractional digits. ## 1 if currency_symbol precedes a positive value, 0 if succeeds. - ("p_cs_precedes", rffi.CHAR), + ("p_cs_precedes", rffi.UCHAR), ## 1 iff a space separates currency_symbol from a positive value. - ("p_sep_by_space", rffi.CHAR), + ("p_sep_by_space", rffi.UCHAR), ## 1 if currency_symbol precedes a negative value, 0 if succeeds. - ("n_cs_precedes", rffi.CHAR), + ("n_cs_precedes", rffi.UCHAR), ## 1 iff a space separates currency_symbol from a negative value. - ("n_sep_by_space", rffi.CHAR), + ("n_sep_by_space", rffi.UCHAR), ## Positive and negative sign positions: ## 0 Parentheses surround the quantity and currency_symbol. @@ -51,8 +51,8 @@ ## 2 The sign string follows the quantity and currency_symbol. ## 3 The sign string immediately precedes the currency_symbol. ## 4 The sign string immediately follows the currency_symbol. - ("p_sign_posn", rffi.CHAR), - ("n_sign_posn", rffi.CHAR), + ("p_sign_posn", rffi.UCHAR), + ("n_sign_posn", rffi.UCHAR), ]) @@ -128,32 +128,36 @@ _lconv = lltype.Ptr(cConfig.lconv) _localeconv = external('localeconv', [], _lconv) +def _copy_grouping(text): + groups = [ ord(group) for group in text ] + if groups: + groups.append(0) + return groups + def localeconv(space): + "() -> dict. Returns numeric and monetary locale-specific parameters." lp = _localeconv() - # hopefully, the localeconv result survives the C library calls - # involved herein - # Numeric information result = { "decimal_point": rffi.charp2str(lp.c_decimal_point), - #"thousands_sep": rffi.getintfield(lp, "c_thousands_sep"), - #"grouping": rffi.getintfield(lp, "c_grouping"), #_copy_grouping(l.grouping)), - #"int_curr_symbol": rffi.getintfield(lp, "c_int_curr_symbol"), - #"currency_symbol": rffi.getintfield(lp, "c_currency_symbol"), - #"mon_decimal_point": rffi.getintfield(lp, "c_mon_decimal_point"), - #"mon_thousands_sep": rffi.getintfield(lp, "c_mon_thousands_sep"), - #"mon_grouping": rffi.getintfield(lp, "c_mon_grouping"), #_copy_grouping(l.mon_grouping)), - #"positive_sign": rffi.getintfield(lp, "c_positive_sign"), - #"negative_sign": rffi.getintfield(lp, "c_negative_sign"), - #"int_frac_digits": rffi.getintfield(lp, "c_int_frac_digits"), - #"frac_digits": rffi.getintfield(lp, "c_frac_digits"), - #"p_cs_precedes": rffi.getintfield(lp, "c_p_cs_precedes"), - #"p_sep_by_space": rffi.getintfield(lp, "c_p_sep_by_space"), - #"n_cs_precedes": rffi.getintfield(lp, "c_n_cs_precedes"), - #"n_sep_by_space": rffi.getintfield(lp, "c_n_sep_by_space"), - #"p_sign_posn": rffi.getintfield(lp, "c_p_sign_posn"), - #"n_sign_posn": rffi.getintfield(lp, "c_n_sign_posn"), + "thousands_sep": rffi.charp2str(lp.c_thousands_sep), + "grouping": _copy_grouping(rffi.charp2str(lp.c_grouping)), # XXX + "int_curr_symbol": rffi.charp2str(lp.c_int_curr_symbol), + "currency_symbol": rffi.charp2str(lp.c_currency_symbol), + "mon_decimal_point": rffi.charp2str(lp.c_mon_decimal_point), + "mon_thousands_sep": rffi.charp2str(lp.c_mon_thousands_sep), + "mon_grouping": _copy_grouping(rffi.charp2str(lp.c_mon_grouping)), # XXX + "positive_sign": rffi.charp2str(lp.c_positive_sign), + "negative_sign": rffi.charp2str(lp.c_negative_sign), + "int_frac_digits": lp.c_int_frac_digits, + "frac_digits": lp.c_frac_digits, + "p_cs_precedes": lp.c_p_cs_precedes, + "p_sep_by_space": lp.c_p_sep_by_space, + "n_cs_precedes": lp.c_n_cs_precedes, + "n_sep_by_space": lp.c_n_sep_by_space, + "p_sign_posn": lp.c_p_sign_posn, + "n_sign_posn": lp.c_n_sign_posn, } return space.wrap(result) Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Fri Feb 13 21:59:10 2009 @@ -63,6 +63,36 @@ assert string.lowercase != lcase assert string.uppercase != ucase + def test_localeconv(self): + skip("raise BytecodeCorruption - wtf?") + import _locale + + lconv_c = { + "currency_symbol": "", + "decimal_point": ".", + "frac_digits": 127, + "grouping": [], + "int_curr_symbol": "", + "int_frac_digits": 127, + "mon_decimal_point": "", + "mon_grouping": [], + "mon_thousands_sep": "", + "n_cs_precedes": 127, + "n_sep_by_space": 127, + "n_sign_posn": 127, + "negative_sign": "", + "p_cs_precedes": 127, + "p_sep_by_space": 127, + "p_sign_posn": 127, + "positive_sign": "", + "thousands_sep": "" } + + _locale.setlocale(_locale.LC_ALL, "C") + + lconv = _locale.localeconv() + for k, v in lconv_c.items(): + assert lconv[k] == v + def test_str_float(self): import _locale import locale From getxsick at codespeak.net Fri Feb 13 21:59:24 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Fri, 13 Feb 2009 21:59:24 +0100 (CET) Subject: [pypy-svn] r61854 - pypy/trunk/pypy/lib Message-ID: <20090213205924.2FE9D168562@codespeak.net> Author: getxsick Date: Fri Feb 13 21:59:23 2009 New Revision: 61854 Modified: pypy/trunk/pypy/lib/_locale.py Log: (jlg, getxsick) minor bugfix. ctypes version added (in some cases) unnecessary 0 at the end of the list for grouping fields from the lconv structure. Modified: pypy/trunk/pypy/lib/_locale.py ============================================================================== --- pypy/trunk/pypy/lib/_locale.py (original) +++ pypy/trunk/pypy/lib/_locale.py Fri Feb 13 21:59:23 2009 @@ -215,7 +215,8 @@ def _copy_grouping(text): groups = [ ord(group) for group in text ] - groups.append(0) + if groups: + groups.append(0) return groups def localeconv(): From jlg at codespeak.net Fri Feb 13 22:28:22 2009 From: jlg at codespeak.net (jlg at codespeak.net) Date: Fri, 13 Feb 2009 22:28:22 +0100 (CET) Subject: [pypy-svn] r61855 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090213212822.7D17E168556@codespeak.net> Author: jlg Date: Fri Feb 13 22:28:21 2009 New Revision: 61855 Modified: pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (getxsick, jlg) BytecodeCorrpution appears in cpython2.6 only Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Fri Feb 13 22:28:21 2009 @@ -142,12 +142,12 @@ result = { "decimal_point": rffi.charp2str(lp.c_decimal_point), "thousands_sep": rffi.charp2str(lp.c_thousands_sep), - "grouping": _copy_grouping(rffi.charp2str(lp.c_grouping)), # XXX + "grouping": _copy_grouping(rffi.charp2str(lp.c_grouping)), "int_curr_symbol": rffi.charp2str(lp.c_int_curr_symbol), "currency_symbol": rffi.charp2str(lp.c_currency_symbol), "mon_decimal_point": rffi.charp2str(lp.c_mon_decimal_point), "mon_thousands_sep": rffi.charp2str(lp.c_mon_thousands_sep), - "mon_grouping": _copy_grouping(rffi.charp2str(lp.c_mon_grouping)), # XXX + "mon_grouping": _copy_grouping(rffi.charp2str(lp.c_mon_grouping)), "positive_sign": rffi.charp2str(lp.c_positive_sign), "negative_sign": rffi.charp2str(lp.c_negative_sign), "int_frac_digits": lp.c_int_frac_digits, Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Fri Feb 13 22:28:21 2009 @@ -64,7 +64,6 @@ assert string.uppercase != ucase def test_localeconv(self): - skip("raise BytecodeCorruption - wtf?") import _locale lconv_c = { From afa at codespeak.net Fri Feb 13 22:42:42 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 13 Feb 2009 22:42:42 +0100 (CET) Subject: [pypy-svn] r61856 - pypy/trunk/pypy/lib Message-ID: <20090213214242.A2947168541@codespeak.net> Author: afa Date: Fri Feb 13 22:42:41 2009 New Revision: 61856 Modified: pypy/trunk/pypy/lib/pwd.py Log: Do not try to import the pwd module on Windows Modified: pypy/trunk/pypy/lib/pwd.py ============================================================================== --- pypy/trunk/pypy/lib/pwd.py (original) +++ pypy/trunk/pypy/lib/pwd.py Fri Feb 13 22:42:41 2009 @@ -10,6 +10,10 @@ exception is raised if the entry asked for cannot be found. """ +import sys +if sys.platform == 'win32': + raise ImportError("No pwd module on Windows") + from ctypes_support import standard_c_lib as libc from ctypes import Structure, POINTER, c_int, c_char_p From fijal at codespeak.net Fri Feb 13 22:48:05 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 22:48:05 +0100 (CET) Subject: [pypy-svn] r61857 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090213214805.E7A7B168543@codespeak.net> Author: fijal Date: Fri Feb 13 22:48:03 2009 New Revision: 61857 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Log: Do it correctly (at least a bit more). Now delayed list comes with it's own specnode, which makes things vastly easier. Next step - recover from guard failure Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Feb 13 22:48:03 2009 @@ -1,5 +1,4 @@ from pypy.annotation import model as annmodel -from pypy.rpython.annlowlevel import MixLevelHelperAnnotator from pypy.rpython.lltypesystem import lltype, llmemory, rstr from pypy.objspace.flow.model import Variable, Constant, Link, c_last_exception from pypy.rlib import objectmodel @@ -15,6 +14,20 @@ MAX_MAKE_NEW_VARS = 16 +class BuiltinDescr(history.AbstractValue): + pass + +class ListDescr(BuiltinDescr): + def __init__(self, getfunc, setfunc, tp): + self.setfunc = setfunc + self.getfunc = getfunc + self.tp = tp + + def equals(self, other): + if isinstance(other, ListDescr): + return True + return False + class JitCode(history.AbstractValue): def __init__(self, name): self.name = name @@ -74,6 +87,7 @@ self.rtyper = metainterp.cpu.rtyper self.cpu = metainterp.cpu self.policy = policy + self.list_cache = {} def make_portal_bytecode(self, graph): log.info("making JitCodes...") @@ -125,6 +139,29 @@ metainterp.builtins_keys.append(key) metainterp.builtins_values.append(value) + + def list_descr_for_tp(self, TP): + try: + return self.list_cache[TP.TO] + except KeyError: + rtyper = self.rtyper + args = [TP, lltype.Signed, TP.TO.OF] + setfunc = support.builtin_func_for_spec(rtyper, 'list.setitem', + args, lltype.Void) + getfunc = support.builtin_func_for_spec(rtyper, 'list.getitem', + args[:-1], TP.TO.OF) + if isinstance(TP.TO.OF, lltype.Number): + tp = "int" + else: + tp = "ptr" + ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), + history.ConstAddr(setfunc.value, self.cpu), + tp) + self.list_cache[TP.TO] = ld + return ld + + + class BytecodeMaker(object): debug = True @@ -515,10 +552,11 @@ if isinstance(arg.concretetype, lltype.Ptr): # XXX very complex logic for getting all things # that are pointers, but not objects - if not (isinstance(arg.concretetype.TO, lltype.GcStruct) and - (heaptracker.get_vtable_for_gcstruct(self.cpu, - arg.concretetype.TO))): - self.emit('guard_builtin', self.var_position(arg)) + if isinstance(arg.concretetype.TO, lltype.GcArray): + descr = self.codewriter.list_descr_for_tp( + arg.concretetype) + self.emit('guard_builtin', self.var_position(arg), + self.get_position(descr)) elif op.args[0].value == 'can_enter_jit': self.emit('can_enter_jit') @@ -559,21 +597,10 @@ def handle_builtin_call(self, op): oopspec_name, args = support.decode_builtin_call(op) - args_s = [annmodel.lltype_to_annotation(v.concretetype) - for v in args] - if '.' not in oopspec_name: # 'newxxx' operations - LIST_OR_DICT = op.result.concretetype - bk = self.codewriter.rtyper.annotator.bookkeeper - args_s.insert(0, annmodel.SomePBC([bk.getdesc(LIST_OR_DICT.TO)])) - else: - LIST_OR_DICT = args[0].concretetype - s_result = annmodel.lltype_to_annotation(op.result.concretetype) - impl = support.setup_extra_builtin(oopspec_name, len(args_s)) - # - mixlevelann = MixLevelHelperAnnotator(self.codewriter.rtyper) - c_func = mixlevelann.constfunc(impl, args_s, s_result) - mixlevelann.finish() - # + ll_args = [v.concretetype for v in args] + c_func = support.builtin_func_for_spec(self.codewriter.rtyper, + oopspec_name, ll_args, + op.result.concretetype) if oopspec_name.endswith('_foldable'): opname = 'green_call_%s' else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 22:48:03 2009 @@ -7,8 +7,10 @@ VirtualizableSpecNode, NotSpecNode, DelayedSpecNode, - SpecNodeWithBox) + SpecNodeWithBox, + DelayedListSpecNode) from pypy.rlib.objectmodel import we_are_translated +from pypy.jit.metainterp.codewriter import ListDescr class CancelInefficientLoop(Exception): pass @@ -110,6 +112,8 @@ return NotSpecNode() return FixedClassSpecNode(known_class) if not other.escaped: + # XXX write a spec node + assert not isinstance(known_class, ListDescr) fields = [] lst = other.curfields.items() lst.sort() @@ -128,6 +132,8 @@ for ofs in lst: specnode = SpecNodeWithBox(self.origfields[ofs].source) fields.append((ofs, specnode)) + if isinstance(known_class, ListDescr): + return DelayedListSpecNode(known_class, fields) return DelayedSpecNode(known_class, fields) else: assert self is other @@ -243,7 +249,7 @@ elif opname == 'guard_builtin': instnode = self.nodes[op.args[0]] # all builtins have equal classes - instnode.cls = InstanceNode(ConstInt(0)) + instnode.cls = InstanceNode(op.args[1]) continue elif opname == 'setfield_gc': instnode = self.getnode(op.args[0]) @@ -543,8 +549,14 @@ # we need to invalidate everything for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): - newoperations.append(ResOperation('setfield_gc', - [node.source, ConstInt(ofs), valuenode.source], [])) + # XXX move to IntanceNode eventually + if isinstance(node.cls.source, ListDescr): + newoperations.append(ResOperation('setitem', + [node.cls.source.setfunc, node.source, + ConstInt(ofs), valuenode.source], [])) + else: + newoperations.append(ResOperation('setfield_gc', + [node.source, ConstInt(ofs), valuenode.source], [])) node.dirtyfields = {} node.cleanfields = {} Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Feb 13 22:48:03 2009 @@ -74,7 +74,7 @@ args += (indirectcallset, ) elif argspec == "builtin": builtin = self.load_const_arg() - assert isinstance(builtin, codewriter.BuiltinCall) + assert isinstance(builtin, codewriter.BuiltinDescr) args += (builtin, ) elif argspec == "virtualizabledesc": from virtualizable import VirtualizableDesc @@ -419,9 +419,9 @@ self.generate_guard(pc, 'guard_class', box, [clsbox]) return clsbox - @arguments("orgpc", "box") - def opimpl_guard_builtin(self, pc, box): - self.generate_guard(pc, "guard_builtin", box) + @arguments("orgpc", "box", "builtin") + def opimpl_guard_builtin(self, pc, box, builtin): + self.generate_guard(pc, "guard_builtin", box, [builtin]) @arguments("orgpc", "box", "virtualizabledesc", "int") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Fri Feb 13 22:48:03 2009 @@ -151,6 +151,39 @@ [instnode.source, ConstInt(ofs)], [box])) newboxlist.append(box) +class DelayedListSpecNode(DelayedSpecNode): + + def expand_boxlist(self, instnode, newboxlist, oplist): + from pypy.jit.metainterp.history import ResOperation, ConstInt + + newboxlist.append(instnode.source) + for ofs, subspecnode in self.fields: + assert isinstance(subspecnode, SpecNodeWithBox) + if oplist is None: + instnode.cleanfields[ofs] = instnode.origfields[ofs] + newboxlist.append(instnode.curfields[ofs].source) + else: + if ofs in instnode.cleanfields: + newboxlist.append(instnode.cleanfields[ofs].source) + else: + xxx + box = subspecnode.box.clonebox() + oplist.append(ResOperation('setitem', + [instnode.source, ConstInt(ofs)], [box])) + newboxlist.append(box) + + def extract_runtime_data(self, cpu, valuebox, resultlist): + from pypy.jit.metainterp.codewriter import ListDescr + + resultlist.append(valuebox) + ld = self.known_class + assert isinstance(ld, ListDescr) + for ofs, subspecnode in self.fields: + fieldbox = cpu.execute_operation('getitem', + [ld.getfunc, valuebox, ConstInt(ofs)], + ld.tp) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) + class VirtualizableSpecNode(VirtualizedSpecNode): def equals(self, other): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Fri Feb 13 22:48:03 2009 @@ -10,6 +10,7 @@ from pypy.translator.translator import TranslationContext from pypy.annotation.policy import AnnotatorPolicy from pypy.annotation import model as annmodel +from pypy.rpython.annlowlevel import MixLevelHelperAnnotator def getargtypes(annotator, values): if values is None: # for backend tests producing stand-alone exe's @@ -178,3 +179,20 @@ return get_call_oopspec_opargs(fnobj, opargs) else: raise ValueError(op.opname) + +def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res): + args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] + if '.' not in oopspec_name: # 'newxxx' operations + LIST_OR_DICT = op.result.concretetype + bk = self.codewriter.rtyper.annotator.bookkeeper + args_s.insert(0, annmodel.SomePBC([bk.getdesc(LIST_OR_DICT.TO)])) + else: + LIST_OR_DICT = ll_args[0] + s_result = annmodel.lltype_to_annotation(ll_res) + impl = setup_extra_builtin(oopspec_name, len(args_s)) + # + mixlevelann = MixLevelHelperAnnotator(rtyper) + c_func = mixlevelann.constfunc(impl, args_s, s_result) + mixlevelann.finish() + # + return c_func From fijal at codespeak.net Fri Feb 13 23:15:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 13 Feb 2009 23:15:48 +0100 (CET) Subject: [pypy-svn] r61858 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213221548.D8DA4168552@codespeak.net> Author: fijal Date: Fri Feb 13 23:15:48 2009 New Revision: 61858 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: A bunch of trivial fixes. For example to get rid of guard_no_exception when they're mutliple. Need more tests though Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Fri Feb 13 23:15:48 2009 @@ -74,15 +74,19 @@ always_pure_operations[_opname] = None if not _opdesc.sideeffects: operations_without_side_effects[_opname] = None + if not _opdesc.canraise: + operation_never_raises[_opname] = None # XXX fish fish fish operations_without_side_effects['getfield_gc'] = None operations_without_side_effects = {} always_pure_operations = {} +operation_never_raises = {} for guard in ['guard_no_exception', 'guard_exception', 'guard_true', 'guard_false', 'guard_value', 'guard_class']: always_pure_operations[guard] = True + operation_never_raises[guard] = True setup() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 13 23:15:48 2009 @@ -1,7 +1,8 @@ from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, MergePoint, ResOperation, Jump) from pypy.jit.metainterp.heaptracker import (always_pure_operations, - operations_without_side_effects) + operations_without_side_effects, + operation_never_raises) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, VirtualInstanceSpecNode, VirtualizableSpecNode, @@ -423,6 +424,7 @@ def optimize_loop(self): newoperations = [] + exception_might_have_happened = False mp = self.loop.operations[0] if mp.opname == 'merge_point': assert len(mp.args) == len(self.specnodes) @@ -469,6 +471,15 @@ if opname == 'guard_true' or opname == 'guard_false': if self.nodes[op.args[0]].const: continue + if (opname == 'guard_no_exception' or + opname == 'guard_exception'): + if exception_might_have_happened: + continue + exception_might_have_happened = False + if opname == 'guard_value': + if (self.nodes[op.args[0]].const and + self.nodes[op.args[1]].const): + continue op = self.optimize_guard(op) newoperations.append(op) continue @@ -537,6 +548,8 @@ continue elif opname not in operations_without_side_effects: self.cleanup_field_caches(newoperations) + if opname not in operation_never_raises: + exception_might_have_happened = True for box in op.results: instnode = InstanceNode(box) self.nodes[box] = instnode @@ -550,7 +563,8 @@ for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): # XXX move to IntanceNode eventually - if isinstance(node.cls.source, ListDescr): + if (node.cls is not None and + isinstance(node.cls.source, ListDescr)): newoperations.append(ResOperation('setitem', [node.cls.source.setfunc, node.source, ConstInt(ofs), valuenode.source], [])) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Fri Feb 13 23:15:48 2009 @@ -183,8 +183,8 @@ def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res): args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if '.' not in oopspec_name: # 'newxxx' operations - LIST_OR_DICT = op.result.concretetype - bk = self.codewriter.rtyper.annotator.bookkeeper + LIST_OR_DICT = ll_res + bk = rtyper.annotator.bookkeeper args_s.insert(0, annmodel.SomePBC([bk.getdesc(LIST_OR_DICT.TO)])) else: LIST_OR_DICT = ll_args[0] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 13 23:15:48 2009 @@ -684,3 +684,32 @@ ]) +# ____________________________________________________________ + +class M: + locals().update(A.__dict__) # :-) + sum3 = BoxInt(3) + v3 = BoxInt(4) + ops = [ + MergePoint('merge_point', [sum, n1], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), + ResOperation('int_sub', [v, ConstInt(1)], [v2]), + ResOperation('int_add', [sum, v], [sum2]), + ResOperation('escape', [n1], []), + Jump('jump', [sum2, n1], []), + ] + +def test_M_optimize_loop(): + spec = PerfectSpecializer(Loop(M.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [L.sum, L.n1, L.v], []), + ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), + ResOperation('int_add', [L.sum, L.v], [L.sum2]), + ResOperation('escape', [L.n1], []), + ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], [ANY]), + Jump('jump', [L.sum2, L.n1, ANY], []), + ]) From fijal at codespeak.net Sat Feb 14 00:17:26 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 00:17:26 +0100 (CET) Subject: [pypy-svn] r61860 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213231726.A28B516856A@codespeak.net> Author: fijal Date: Sat Feb 14 00:17:26 2009 New Revision: 61860 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: A bit of fixes and a test that should test something else, but a fix for it anyway :) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sat Feb 14 00:17:26 2009 @@ -487,6 +487,7 @@ c_fieldname.value) self.emit(offset) self.register_var(op.result) + self._eventualy_builtin(op.result) def serialize_op_setfield(self, op): if self.is_typeptr_getset(op): @@ -549,19 +550,22 @@ range(0, 2*(len(op.args) - 2), 2)) for i in range(2, len(op.args)): arg = op.args[i] - if isinstance(arg.concretetype, lltype.Ptr): - # XXX very complex logic for getting all things - # that are pointers, but not objects - if isinstance(arg.concretetype.TO, lltype.GcArray): - descr = self.codewriter.list_descr_for_tp( - arg.concretetype) - self.emit('guard_builtin', self.var_position(arg), - self.get_position(descr)) + self._eventualy_builtin(arg) elif op.args[0].value == 'can_enter_jit': self.emit('can_enter_jit') self.emit_varargs(op.args[2:]) + def _eventualy_builtin(self, arg): + if isinstance(arg.concretetype, lltype.Ptr): + # XXX very complex logic for getting all things + # that are pointers, but not objects + if isinstance(arg.concretetype.TO, lltype.GcArray): + descr = self.codewriter.list_descr_for_tp(arg.concretetype) + self.emit('guard_builtin', self.var_position(arg), + self.get_position(descr)) + + #def serialize_op_direct_call(self, op): # color = support.guess_call_kind(self.codewriter.hannotator, op) # return getattr(self, 'handle_%s_call' % color)(op) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 00:17:26 2009 @@ -148,14 +148,14 @@ node = other.curfields[ofs] specnode = self.origfields[ofs].intersect(node) elif ofs in self.origfields: - specnode = NotSpecNode() + node = self.origfields[ofs] + specnode = node.intersect(node) else: # ofs in other.curfields node = other.curfields[ofs] self.origfields[ofs] = InstanceNode(node.source.clonebox()) specnode = NotSpecNode() fields.append((ofs, specnode)) - return VirtualizableSpecNode(known_class, fields) def __repr__(self): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Sat Feb 14 00:17:26 2009 @@ -12,6 +12,7 @@ from pypy.jit.metainterp.virtualizable import VirtualizableDesc from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, equaloplists, Loop) +from pypy.jit.metainterp.codewriter import ListDescr # ____________________________________________________________ @@ -21,10 +22,11 @@ ('vable_base', llmemory.Address), ('vable_rti', VABLERTIPTR), ('x', lltype.Signed), + ('l', lltype.Ptr(lltype.GcArray(lltype.Signed))), ('node', lltype.Ptr(NODE)), hints = {'virtualizable2': True}, adtmeths = {'access': VirtualizableAccessor()}) -XY._adtmeths['access'].initialize(XY, ['x', 'node']) +XY._adtmeths['access'].initialize(XY, ['x', 'node', 'l']) xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) xy_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 3, immortal=True) @@ -60,6 +62,7 @@ class A: ofs_node = runner.CPU.fielddescrof(XY, 'node') + ofs_l = runner.CPU.fielddescrof(XY, 'l') ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) # @@ -190,3 +193,37 @@ assert len(spec.specnodes[0].fields) == 1 assert spec.specnodes[0].fields[0][0] == C.ofs_node assert isinstance(spec.specnodes[0].fields[0][1], NotSpecNode) + + +# ____________________________________________________________ + +class D: + class SomeDescr(ListDescr): + def __init__(self): + pass + + locals().update(A.__dict__) + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + v2 = BoxInt(13) + l = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) + ops = [ + MergePoint('merge_point', [fr], []), + ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), + ConstInt(ofs_node)], []), + # + ResOperation('getfield_gc', [fr, ConstInt(ofs_l)], [l]), + ResOperation('guard_builtin', [l, SomeDescr()], []), + ResOperation('getitem', [None, l, ConstInt(0)], [v2]), + ResOperation('setitem', [None, l, ConstInt(0), v2], []), + Jump('jump', [fr], []), + ] + ops[1].vdesc = xy_desc + +def test_D_intersect_input_and_output(): + spec = PerfectSpecializer(Loop(D.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + assert spec.nodes[D.fr].escaped + assert spec.nodes[D.fr].virtualized + assert spec.nodes[D.l].escaped + assert spec.nodes[D.l].expanded_fields.keys() == [0] From fijal at codespeak.net Sat Feb 14 00:38:54 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 00:38:54 +0100 (CET) Subject: [pypy-svn] r61861 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090213233854.8983F168561@codespeak.net> Author: fijal Date: Sat Feb 14 00:38:51 2009 New Revision: 61861 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: next tests to pass Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Sat Feb 14 00:38:51 2009 @@ -0,0 +1,27 @@ + +import py +py.test.skip("next to go") +from pypy.rlib.jit import JitDriver +from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin + +class ListTests: + def test_basic(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) + def f(n): + l = [0] + while n > 0: + myjitdriver.can_enter_jit(n=n, l=l) + myjitdriver.jit_merge_point(n=n, l=l) + x = l[0] + l[0] = x + 1 + n -= 1 + return l[0] + + res = self.meta_interp(f, [10]) + assert res == f(10) + + self.check_loops(getitem=0, setitem=1, guard_exception=0, + guard_no_exception=0) + +class TestLLtype(ListTests, LLJitMixin): + pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Sat Feb 14 00:38:51 2009 @@ -220,10 +220,11 @@ ops[1].vdesc = xy_desc def test_D_intersect_input_and_output(): + py.test.skip("not yet") spec = PerfectSpecializer(Loop(D.ops)) spec.find_nodes() spec.intersect_input_and_output() assert spec.nodes[D.fr].escaped assert spec.nodes[D.fr].virtualized - assert spec.nodes[D.l].escaped + assert not spec.nodes[D.l].escaped assert spec.nodes[D.l].expanded_fields.keys() == [0] From fijal at codespeak.net Sat Feb 14 00:51:10 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 00:51:10 +0100 (CET) Subject: [pypy-svn] r61862 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090213235110.2BF84168563@codespeak.net> Author: fijal Date: Sat Feb 14 00:51:06 2009 New Revision: 61862 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Log: good. Pass the first test about lists Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 00:51:06 2009 @@ -30,6 +30,9 @@ # last two cases are for virtualizables only self.allocations = [] self.setfields = [] + # the same as above, but for lists and for running setitem + self.list_allocations = [] + self.setitems = [] def deal_with_box(self, box, nodes, liveboxes, memo): if isinstance(box, Const): @@ -377,7 +380,11 @@ rev_boxes[fieldbox] = len(liveboxes) liveboxes.append(fieldbox) fieldindex = ~rev_boxes[fieldbox] - storage.setfields.append((index, ofs, fieldindex)) + if isinstance(node.cls.source, ListDescr): + f = node.cls.source.setfunc + storage.setitems.append((f, index, ofs, fieldindex)) + else: + storage.setfields.append((index, ofs, fieldindex)) if not we_are_translated(): items = [box for box in liveboxes if isinstance(box, Box)] assert len(dict.fromkeys(items)) == len(items) @@ -473,7 +480,7 @@ continue if (opname == 'guard_no_exception' or opname == 'guard_exception'): - if exception_might_have_happened: + if not exception_might_have_happened: continue exception_might_have_happened = False if opname == 'guard_value': @@ -606,6 +613,11 @@ new_instnode = self.nodes[jump_op.args[i]] old_specnode.adapt_to(new_instnode) +def box_from_index(allocated_boxes, boxes_from_frame, index): + if index < 0: + return boxes_from_frame[~index] + return allocated_boxes[index] + def rebuild_boxes_from_guard_failure(guard_op, history, boxes_from_frame): allocated_boxes = [] storage = guard_op.storage_info @@ -617,17 +629,21 @@ 'ptr', False) allocated_boxes.append(instbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: - if index_in_arglist < 0: - fieldbox = boxes_from_frame[~index_in_arglist] - else: - fieldbox = allocated_boxes[index_in_arglist] - if index_in_alloc < 0: - box = boxes_from_frame[~index_in_alloc] - else: - box = allocated_boxes[index_in_alloc] + fieldbox = box_from_index(allocated_boxes, boxes_from_frame, + index_in_arglist) + box = box_from_index(allocated_boxes, boxes_from_frame, + index_in_alloc) history.execute_and_record('setfield_gc', [box, ConstInt(ofs), fieldbox], 'void', False) + for setfunc, index_in_alloc, ofs, index_in_arglist in storage.setitems: + itembox = box_from_index(allocated_boxes, boxes_from_frame, + index_in_arglist) + box = box_from_index(allocated_boxes, boxes_from_frame, + index_in_alloc) + history.execute_and_record('setitem', + [setfunc, box, ConstInt(ofs), itembox], + 'void', False) newboxes = [] for index in storage.indices: if index < 0: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Sat Feb 14 00:51:06 2009 @@ -1,6 +1,5 @@ import py -py.test.skip("next to go") from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin From fijal at codespeak.net Sat Feb 14 01:02:16 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 01:02:16 +0100 (CET) Subject: [pypy-svn] r61863 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214000216.7E7C7168557@codespeak.net> Author: fijal Date: Sat Feb 14 01:02:15 2009 New Revision: 61863 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Log: Oops, fix the test. As of now, test_tl and test_tlc does not work (for obscure reasons), but everything else works. We need more tests about lazy things Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 01:02:15 2009 @@ -380,7 +380,7 @@ rev_boxes[fieldbox] = len(liveboxes) liveboxes.append(fieldbox) fieldindex = ~rev_boxes[fieldbox] - if isinstance(node.cls.source, ListDescr): + if node.cls is not None and isinstance(node.cls.source, ListDescr): f = node.cls.source.setfunc storage.setitems.append((f, index, ofs, fieldindex)) else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Sat Feb 14 01:02:15 2009 @@ -1,3 +1,5 @@ +import py + from pypy.rpython.lltypesystem import lltype, rclass, llmemory from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR from pypy.rpython.lltypesystem.rvirtualizable2 import VirtualizableAccessor @@ -192,7 +194,7 @@ assert isinstance(spec.specnodes[0], VirtualizableSpecNode) assert len(spec.specnodes[0].fields) == 1 assert spec.specnodes[0].fields[0][0] == C.ofs_node - assert isinstance(spec.specnodes[0].fields[0][1], NotSpecNode) + assert isinstance(spec.specnodes[0].fields[0][1], VirtualInstanceSpecNode) # ____________________________________________________________ @@ -220,7 +222,7 @@ ops[1].vdesc = xy_desc def test_D_intersect_input_and_output(): - py.test.skip("not yet") + py.test.skip("XXX") spec = PerfectSpecializer(Loop(D.ops)) spec.find_nodes() spec.intersect_input_and_output() From antocuni at codespeak.net Sat Feb 14 09:48:47 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 14 Feb 2009 09:48:47 +0100 (CET) Subject: [pypy-svn] r61865 - pypy/branch/oo-jit/pypy/module/pypyjit Message-ID: <20090214084847.EEE6F168536@codespeak.net> Author: antocuni Date: Sat Feb 14 09:48:44 2009 New Revision: 61865 Modified: pypy/branch/oo-jit/pypy/module/pypyjit/newbool.py Log: typo Modified: pypy/branch/oo-jit/pypy/module/pypyjit/newbool.py ============================================================================== --- pypy/branch/oo-jit/pypy/module/pypyjit/newbool.py (original) +++ pypy/branch/oo-jit/pypy/module/pypyjit/newbool.py Sat Feb 14 09:48:44 2009 @@ -82,7 +82,7 @@ else: gv_res = curbuilder.genop2("int_eq", gv_int1, gv_int2) #return rvalue.IntRedBox(self.boolkind, gv_res) - return rvalue.IntRedBox(self.boolkind, gv_res) + return rvalue.IntRedBox(gv_res) class VirtualBool(rcontainer.VirtualContainer): From fijal at codespeak.net Sat Feb 14 10:22:42 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 10:22:42 +0100 (CET) Subject: [pypy-svn] r61866 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090214092242.ACC99168548@codespeak.net> Author: fijal Date: Sat Feb 14 10:22:42 2009 New Revision: 61866 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Log: A test and a fix Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Sat Feb 14 10:22:42 2009 @@ -17,10 +17,26 @@ return l[0] res = self.meta_interp(f, [10]) - assert res == f(10) - + assert res == f(10) self.check_loops(getitem=0, setitem=1, guard_exception=0, - guard_no_exception=0) + guard_no_exception=0) + + def test_list_escapes(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) + def f(n): + l = [0] * (n + 1) + while n > 0: + myjitdriver.can_enter_jit(n=n, l=l) + myjitdriver.jit_merge_point(n=n, l=l) + x = l[0] + l[0] = x + 1 + l[n] = n + n -= 1 + return l[3] + + res = self.meta_interp(f, [10]) + assert res == f(10) + self.check_loops(setitem=2) class TestLLtype(ListTests, LLJitMixin): pass From fijal at codespeak.net Sat Feb 14 10:42:27 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 10:42:27 +0100 (CET) Subject: [pypy-svn] r61867 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090214094227.EA22D16852D@codespeak.net> Author: fijal Date: Sat Feb 14 10:42:25 2009 New Revision: 61867 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Log: A test that fails for mysterious reasons to me, seems jit-unrelated Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Sat Feb 14 10:42:25 2009 @@ -36,7 +36,33 @@ res = self.meta_interp(f, [10]) assert res == f(10) + self.check_loops(setitem=2, getitem=1) + + def test_list_indexerror(self): + # this is an example where IndexError is raised before + # even getting to the JIT + py.test.skip("I suspect bug somewhere outside of the JIT") + myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) + def f(n): + l = [0] + while n > 0: + myjitdriver.can_enter_jit(n=n, l=l) + myjitdriver.jit_merge_point(n=n, l=l) + l[n] = n + n -= 1 + return l[3] + + def g(n): + try: + f(n) + return 0 + except IndexError: + return 42 + + res = self.meta_interp(g, [10]) + assert res == 42 self.check_loops(setitem=2) + class TestLLtype(ListTests, LLJitMixin): pass From fijal at codespeak.net Sat Feb 14 11:21:35 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 11:21:35 +0100 (CET) Subject: [pypy-svn] r61868 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214102135.CE35116852D@codespeak.net> Author: fijal Date: Sat Feb 14 11:21:33 2009 New Revision: 61868 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: A bit different support for builtin calls. Now we have around ListDescr. Still don't know what to do with malloc Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sat Feb 14 11:21:33 2009 @@ -146,10 +146,10 @@ except KeyError: rtyper = self.rtyper args = [TP, lltype.Signed, TP.TO.OF] - setfunc = support.builtin_func_for_spec(rtyper, 'list.setitem', - args, lltype.Void) - getfunc = support.builtin_func_for_spec(rtyper, 'list.getitem', - args[:-1], TP.TO.OF) + setfunc, _ = support.builtin_func_for_spec(rtyper, 'list.setitem', + args, lltype.Void) + getfunc, _ = support.builtin_func_for_spec(rtyper, 'list.getitem', + args[:-1], TP.TO.OF) if isinstance(TP.TO.OF, lltype.Number): tp = "int" else: @@ -602,25 +602,31 @@ def handle_builtin_call(self, op): oopspec_name, args = support.decode_builtin_call(op) ll_args = [v.concretetype for v in args] - c_func = support.builtin_func_for_spec(self.codewriter.rtyper, - oopspec_name, ll_args, - op.result.concretetype) + c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper, + oopspec_name, ll_args, + op.result.concretetype) if oopspec_name.endswith('_foldable'): opname = 'green_call_%s' else: opname = 'residual_call_%s' - if oopspec_name == 'list.getitem': - opname = 'getitem_%s' - if oopspec_name == 'list.setitem': - opname = 'setitem_%s' + if oopspec_name.startswith('list') or oopspec_name == 'newlist': + if oopspec_name == 'list.getitem': + opname = 'getitem' + elif oopspec_name == 'list.setitem': + opname = 'setitem' + elif oopspec_name == 'newlist': + opname = 'newlist' + else: + raise NotImplementedError("not supported %s" % oopspec_name) + self.emit(opname) + ld = self.codewriter.list_descr_for_tp(TP) + self.emit(self.get_position(ld)) + self.emit_varargs(args) + self.register_var(op.result) + return self.emit(opname % getkind_num(self.cpu, op.result.concretetype)) self.emit_varargs([c_func] + args) self.register_var(op.result) - # - #if (oopspec_name.startswith('newlist') or - # oopspec_name.startswith('list.')): - # self.codewriter.register_list_op(c_func.value, oopspec_name, - # LIST_OR_DICT) # def serialize_op_indirect_call(self, op): # xxx Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sat Feb 14 11:21:33 2009 @@ -375,13 +375,19 @@ def opimpl_residual_call_void(self, varargs): return self.execute_with_exc('call_void', varargs, 'void') - @arguments("varargs") - def opimpl_getitem__4(self, varargs): - return self.execute_with_exc('getitem', varargs, 'int') - - @arguments("varargs") - def opimpl_setitem_void(self, varargs): - return self.execute_with_exc('setitem', varargs, 'void') + @arguments("builtin", "varargs") + def opimpl_getitem(self, descr, varargs): + args = [descr.getfunc] + varargs + return self.execute_with_exc('getitem', args, descr.tp) + + @arguments("builtin", "varargs") + def opimpl_setitem(self, descr, varargs): + args = [descr.setfunc] + varargs + return self.execute_with_exc('setitem', args, 'void') + + @arguments("builtin", "varargs") + def opimpl_newlist(self, descr, varargs): + return self.execute_with_exc('newlist', varargs, 'ptr') @arguments("indirectcallset", "box", "varargs") def opimpl_indirect_call(self, indirectcallset, box, varargs): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sat Feb 14 11:21:33 2009 @@ -155,6 +155,7 @@ def expand_boxlist(self, instnode, newboxlist, oplist): from pypy.jit.metainterp.history import ResOperation, ConstInt + from pypy.jit.metainterp.codewriter import ListDescr newboxlist.append(instnode.source) for ofs, subspecnode in self.fields: @@ -166,11 +167,12 @@ if ofs in instnode.cleanfields: newboxlist.append(instnode.cleanfields[ofs].source) else: - xxx + ld = instnode.cls.source + assert isinstance(ld, ListDescr) box = subspecnode.box.clonebox() - oplist.append(ResOperation('setitem', - [instnode.source, ConstInt(ofs)], [box])) - newboxlist.append(box) + oplist.append(ResOperation('getitem', + [ld.getfunc, instnode.source, ConstInt(ofs)], [box])) + newboxlist.append(box) def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.codewriter import ListDescr Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Sat Feb 14 11:21:33 2009 @@ -195,4 +195,4 @@ c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() # - return c_func + return c_func, LIST_OR_DICT Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Sat Feb 14 11:21:33 2009 @@ -62,7 +62,6 @@ res = self.meta_interp(g, [10]) assert res == 42 self.check_loops(setitem=2) - class TestLLtype(ListTests, LLJitMixin): pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sat Feb 14 11:21:33 2009 @@ -1,30 +1,32 @@ import py -py.test.skip("XXX") from pypy.rlib.jit import JitDriver, hint -from pypy.jit.hintannotator.policy import StopAtXPolicy -from pyjitpl import get_stats +from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype -from test.test_basic import LLJitMixin, OOJitMixin +from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin class ListTests: def check_all_virtualized(self): - get_stats().check_loops(new=0, new_with_vtable=0, + self.check_loops(new=0, new_with_vtable=0, call__4=0, call__8=0, call_ptr=0) def test_simple_array(self): + jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) lst = [n] n = lst[0] - 1 return n - res = self.meta_interp(f, [10], exceptions=False) + res = self.meta_interp(f, [10]) assert res == 0 get_stats().check_loops(int_sub=1) self.check_all_virtualized() def test_append_pop(self): + py.test.skip("XXX") def f(n): while n > 0: lst = [] @@ -34,11 +36,12 @@ three = lst[0] n = lst.pop() - three return n - res = self.meta_interp(f, [31], exceptions=False) + res = self.meta_interp(f, [31]) assert res == -2 self.check_all_virtualized() def test_insert(self): + py.test.skip("XXX") def f(n): while n > 0: lst = [1, 2, 3] @@ -50,6 +53,7 @@ self.check_all_virtualized() def test_list_escapes(self): + py.test.skip("XXX") def f(n): while True: lst = [] @@ -62,6 +66,7 @@ self.check_all_virtualized() def test_list_reenters(self): + py.test.skip("XXX") def f(n): while n > 0: lst = [] @@ -75,6 +80,7 @@ self.check_all_virtualized() def test_cannot_merge(self): + py.test.skip("XXX") def f(n): while n > 0: lst = [] @@ -89,6 +95,7 @@ self.check_all_virtualized() def test_extend(self): + py.test.skip("XXX") def f(n): while n > 0: lst = [5, 2] From fijal at codespeak.net Sat Feb 14 11:52:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 11:52:56 +0100 (CET) Subject: [pypy-svn] r61869 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090214105256.6C38016853C@codespeak.net> Author: fijal Date: Sat Feb 14 11:52:53 2009 New Revision: 61869 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Enough support to pass the first virtual list test (no virtual list specnode yet) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sat Feb 14 11:52:53 2009 @@ -78,10 +78,14 @@ 'guard_no_exception' : ((), None), 'guard_exception' : (('ptr',), 'ptr'), 'guard_nonvirtualized__4' : (('ptr', 'int'), None), + 'guard_builtin' : (('ptr',), None), 'newstr' : (('int',), 'ptr'), 'strlen' : (('ptr',), 'int'), 'strgetitem' : (('ptr', 'int'), 'int'), 'strsetitem' : (('ptr', 'int', 'int'), None), + 'getitem' : (('ptr', 'ptr', 'int'), 'int'), + 'setitem' : (('ptr', 'ptr', 'int', 'int'), None), + 'newlist' : (('ptr', 'int'), 'ptr'), } # ____________________________________________________________ @@ -549,6 +553,9 @@ def op_guard_pause(self): raise GuardFailed + def op_guard_builtin(self, b): + pass + def op_guard_true(self, value, *livevars): if not value: raise GuardFailed @@ -749,6 +756,15 @@ op_call_ptr = do_call op_call_void = do_call + def op_getitem(self, ll_getitem, lst, item): + return self.do_call(ll_getitem, lst, item) + + def op_setitem(self, ll_setitem, lst, item, val): + self.do_call(ll_setitem, lst, item, val) + + def op_newlist(self, ll_newlist, lgt): + return self.do_call(ll_newlist, lgt) + def op_cast_int_to_ptr(self, i): if i == 0: return dummy_null Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sat Feb 14 11:52:53 2009 @@ -18,10 +18,11 @@ pass class ListDescr(BuiltinDescr): - def __init__(self, getfunc, setfunc, tp): - self.setfunc = setfunc - self.getfunc = getfunc - self.tp = tp + def __init__(self, getfunc, setfunc, malloc_func, tp): + self.setfunc = setfunc + self.getfunc = getfunc + self.malloc_func = malloc_func + self.tp = tp def equals(self, other): if isinstance(other, ListDescr): @@ -150,12 +151,15 @@ args, lltype.Void) getfunc, _ = support.builtin_func_for_spec(rtyper, 'list.getitem', args[:-1], TP.TO.OF) + malloc_func, _ = support.builtin_func_for_spec(rtyper, 'newlist', + [lltype.Signed], TP) if isinstance(TP.TO.OF, lltype.Number): tp = "int" else: tp = "ptr" ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), history.ConstAddr(setfunc.value, self.cpu), + history.ConstAddr(malloc_func.value, self.cpu), tp) self.list_cache[TP.TO] = ld return ld @@ -605,25 +609,27 @@ c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper, oopspec_name, ll_args, op.result.concretetype) + if oopspec_name.startswith('list') or oopspec_name == 'newlist': + if oopspec_name.startswith('list.getitem'): + opname = oopspec_name[len('list.'):] + elif oopspec_name.startswith('list.setitem'): + opname = oopspec_name[len('list.'):] + elif oopspec_name == 'newlist': + opname = 'newlist' + else: + raise NotImplementedError("not supported %s" % oopspec_name) + self.emit(opname) + ld = self.codewriter.list_descr_for_tp(TP) + self.emit(self.get_position(ld)) + self.emit_varargs(args) + self.register_var(op.result) + if opname == 'newlist': + self._eventualy_builtin(op.result) + return if oopspec_name.endswith('_foldable'): opname = 'green_call_%s' else: opname = 'residual_call_%s' - if oopspec_name.startswith('list') or oopspec_name == 'newlist': - if oopspec_name == 'list.getitem': - opname = 'getitem' - elif oopspec_name == 'list.setitem': - opname = 'setitem' - elif oopspec_name == 'newlist': - opname = 'newlist' - else: - raise NotImplementedError("not supported %s" % oopspec_name) - self.emit(opname) - ld = self.codewriter.list_descr_for_tp(TP) - self.emit(self.get_position(ld)) - self.emit_varargs(args) - self.register_var(op.result) - return self.emit(opname % getkind_num(self.cpu, op.result.concretetype)) self.emit_varargs([c_func] + args) self.register_var(op.result) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 11:52:53 2009 @@ -250,6 +250,14 @@ self.nodes[box] = instnode self.first_escaping_op = False continue + elif opname == 'newlist': + box = op.results[0] + instnode = InstanceNode(box, escaped=False) + self.nodes[box] = instnode + self.first_escaping_op = False + # XXX following guard_builtin will set the + # correct class, otherwise it's a mess + continue elif opname == 'guard_builtin': instnode = self.nodes[op.args[0]] # all builtins have equal classes @@ -512,6 +520,12 @@ key = instnode.cls.source.getint() type_cache.class_size[key] = size continue + elif opname == 'newlist': + instnode = self.nodes[op.results[0]] + if not instnode.escaped: + instnode.virtual = True + assert isinstance(instnode.cls.source, ListDescr) + continue elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sat Feb 14 11:52:53 2009 @@ -375,6 +375,7 @@ def opimpl_residual_call_void(self, varargs): return self.execute_with_exc('call_void', varargs, 'void') + @arguments("builtin", "varargs") def opimpl_getitem(self, descr, varargs): args = [descr.getfunc] + varargs @@ -386,8 +387,19 @@ return self.execute_with_exc('setitem', args, 'void') @arguments("builtin", "varargs") + def opimpl_getitem_foldable(self, descr, varargs): + args = [descr.getfunc] + varargs + return self.execute_with_exc('getitem', args, descr.tp, True) + + @arguments("builtin", "varargs") + def opimpl_setitem_foldable(self, descr, varargs): + args = [descr.setfunc] + varargs + return self.execute_with_exc('setitem', args, 'void', True) + + @arguments("builtin", "varargs") def opimpl_newlist(self, descr, varargs): - return self.execute_with_exc('newlist', varargs, 'ptr') + args = [descr.malloc_func] + varargs + op = self.execute_with_exc('newlist', args, 'ptr') @arguments("indirectcallset", "box", "varargs") def opimpl_indirect_call(self, indirectcallset, box, varargs): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sat Feb 14 11:52:53 2009 @@ -8,8 +8,8 @@ class ListTests: def check_all_virtualized(self): - self.check_loops(new=0, new_with_vtable=0, - call__4=0, call__8=0, call_ptr=0) + self.check_loops(new=0, newlist=0, + getitem=0, setitem=0) def test_simple_array(self): jitdriver = JitDriver(greens = [], reds = ['n']) @@ -22,7 +22,7 @@ return n res = self.meta_interp(f, [10]) assert res == 0 - get_stats().check_loops(int_sub=1) + self.check_loops(int_sub=1) self.check_all_virtualized() def test_append_pop(self): From fijal at codespeak.net Sat Feb 14 12:08:53 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 12:08:53 +0100 (CET) Subject: [pypy-svn] r61870 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214110853.5CA57168536@codespeak.net> Author: fijal Date: Sat Feb 14 12:08:52 2009 New Revision: 61870 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: support for virtual lists. There are still two quirks, but I'll address them later Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 12:08:52 2009 @@ -9,7 +9,8 @@ NotSpecNode, DelayedSpecNode, SpecNodeWithBox, - DelayedListSpecNode) + DelayedListSpecNode, + VirtualListSpecNode) from pypy.rlib.objectmodel import we_are_translated from pypy.jit.metainterp.codewriter import ListDescr @@ -46,13 +47,25 @@ virtual = instnode.virtual virtualized = instnode.virtualized if virtual: - alloc_offset = len(self.allocations) - self.allocations.append(instnode.cls.source.getint()) + if isinstance(instnode.cls.source, ListDescr): + ld = instnode.cls.source + assert isinstance(ld, ListDescr) + alloc_offset = len(self.list_allocations) + malloc_func = ld.malloc_func + # XXX grab from somewhere the list length + self.list_allocations.append((malloc_func, 13)) + else: + alloc_offset = len(self.allocations) + self.allocations.append(instnode.cls.source.getint()) res = alloc_offset memo[box] = res for ofs, node in instnode.curfields.items(): num = self.deal_with_box(node.source, nodes, liveboxes, memo) - self.setfields.append((alloc_offset, ofs, num)) + if isinstance(instnode.cls.source, ListDescr): + ld = instnode.cls.source + self.setitems.append((ld.setfunc, alloc_offset, ofs, num)) + else: + self.setfields.append((alloc_offset, ofs, num)) elif virtualized: res = ~len(liveboxes) memo[box] = res @@ -116,8 +129,6 @@ return NotSpecNode() return FixedClassSpecNode(known_class) if not other.escaped: - # XXX write a spec node - assert not isinstance(known_class, ListDescr) fields = [] lst = other.curfields.items() lst.sort() @@ -128,6 +139,8 @@ self.origfields[ofs] = InstanceNode(node.source.clonebox()) specnode = NotSpecNode() fields.append((ofs, specnode)) + if isinstance(known_class, ListDescr): + return VirtualListSpecNode(known_class, fields) return VirtualInstanceSpecNode(known_class, fields) if not other.virtualized and self.expanded_fields: fields = [] @@ -634,6 +647,7 @@ def rebuild_boxes_from_guard_failure(guard_op, history, boxes_from_frame): allocated_boxes = [] + allocated_lists = [] storage = guard_op.storage_info for vtable in storage.allocations: sizebox = ConstInt(type_cache.class_size[vtable]) @@ -642,6 +656,12 @@ [sizebox, vtablebox], 'ptr', False) allocated_boxes.append(instbox) + for malloc_func, lgt in storage.list_allocations: + sizebox = ConstInt(lgt) + [listbox] = history.execute_and_record('newlist', + [malloc_func, sizebox], + 'ptr', False) + allocated_lists.append(listbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: fieldbox = box_from_index(allocated_boxes, boxes_from_frame, index_in_arglist) @@ -653,7 +673,7 @@ for setfunc, index_in_alloc, ofs, index_in_arglist in storage.setitems: itembox = box_from_index(allocated_boxes, boxes_from_frame, index_in_arglist) - box = box_from_index(allocated_boxes, boxes_from_frame, + box = box_from_index(allocated_lists, boxes_from_frame, index_in_alloc) history.execute_and_record('setitem', [setfunc, box, ConstInt(ofs), itembox], @@ -663,6 +683,7 @@ if index < 0: newboxes.append(boxes_from_frame[~index]) else: + # XXX allocated_boxes vs allocated_lists newboxes.append(allocated_boxes[index]) return newboxes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sat Feb 14 12:08:52 2009 @@ -193,14 +193,33 @@ return False return SpecNodeWithFields.equals(self, other) -class VirtualInstanceSpecNode(SpecNodeWithFields): +class VirtualSpecNode(SpecNodeWithFields): def mutate_nodes(self, instnode): SpecNodeWithFields.mutate_nodes(self, instnode) instnode.virtual = True +class VirtualInstanceSpecNode(VirtualSpecNode): + def equals(self, other): if not isinstance(other, VirtualInstanceSpecNode): return False return SpecNodeWithFields.equals(self, other) +class VirtualListSpecNode(VirtualSpecNode): + + def equals(self, other): + if not isinstance(other, VirtualListSpecNode): + return False + return SpecNodeWithFields.equals(self, other) + + def extract_runtime_data(self, cpu, valuebox, resultlist): + from pypy.jit.metainterp.codewriter import ListDescr + + for ofs, subspecnode in self.fields: + cls = self.known_class + assert isinstance(cls, ListDescr) + fieldbox = cpu.execute_operation('getitem', + [cls.getfunc, valuebox, ConstInt(ofs)], + cls.tp) + subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sat Feb 14 12:08:52 2009 @@ -25,6 +25,22 @@ self.check_loops(int_sub=1) self.check_all_virtualized() + def test_list_pass_around(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'l']) + def f(n): + l = [3] + while n > 0: + jitdriver.can_enter_jit(n=n, l=l) + jitdriver.jit_merge_point(n=n, l=l) + x = l[0] + l = [x + 1] + n -= 1 + return l[0] + + res = self.meta_interp(f, [10]) + assert res == f(10) + self.check_all_virtualized() + def test_append_pop(self): py.test.skip("XXX") def f(n): From fijal at codespeak.net Sat Feb 14 12:16:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 12:16:11 +0100 (CET) Subject: [pypy-svn] r61871 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090214111611.F0036168536@codespeak.net> Author: fijal Date: Sat Feb 14 12:16:11 2009 New Revision: 61871 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Deal with one issue, test now passes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 12:16:11 2009 @@ -53,11 +53,12 @@ alloc_offset = len(self.list_allocations) malloc_func = ld.malloc_func # XXX grab from somewhere the list length - self.list_allocations.append((malloc_func, 13)) + self.list_allocations.append((malloc_func, 133)) + res = (alloc_offset + 1) << 16 else: alloc_offset = len(self.allocations) self.allocations.append(instnode.cls.source.getint()) - res = alloc_offset + res = alloc_offset memo[box] = res for ofs, node in instnode.curfields.items(): num = self.deal_with_box(node.source, nodes, liveboxes, memo) @@ -300,6 +301,8 @@ box = op.results[0] self.find_nodes_getfield(instnode, field, box) continue + else: + self.cleanup_fields(instnode) elif opname == 'setitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] @@ -308,6 +311,8 @@ self.find_nodes_setfield(instnode, field, self.getnode(op.args[3])) continue + else: + self.cleanup_fields(instnode) elif opname == 'guard_class': instnode = self.getnode(op.args[0]) if instnode.cls is None: @@ -643,6 +648,8 @@ def box_from_index(allocated_boxes, boxes_from_frame, index): if index < 0: return boxes_from_frame[~index] + if index > 0xffff: + return allocated_boxes[(index - 1) >> 16] return allocated_boxes[index] def rebuild_boxes_from_guard_failure(guard_op, history, boxes_from_frame): @@ -682,8 +689,9 @@ for index in storage.indices: if index < 0: newboxes.append(boxes_from_frame[~index]) + elif index > 0xffff: + newboxes.append(allocated_lists[(index - 1) >> 16]) else: - # XXX allocated_boxes vs allocated_lists newboxes.append(allocated_boxes[index]) return newboxes From fijal at codespeak.net Sat Feb 14 12:20:58 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 12:20:58 +0100 (CET) Subject: [pypy-svn] r61872 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214112058.95D91168536@codespeak.net> Author: fijal Date: Sat Feb 14 12:20:58 2009 New Revision: 61872 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Log: deal with known_length Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 12:20:58 2009 @@ -52,8 +52,9 @@ assert isinstance(ld, ListDescr) alloc_offset = len(self.list_allocations) malloc_func = ld.malloc_func - # XXX grab from somewhere the list length - self.list_allocations.append((malloc_func, 133)) + assert instnode.known_length != -1 + self.list_allocations.append((malloc_func, + instnode.known_length)) res = (alloc_offset + 1) << 16 else: alloc_offset = len(self.allocations) @@ -99,6 +100,7 @@ self.cleanfields = {} self.dirtyfields = {} self.expanded_fields = {} + self.known_length = -1 def escape_if_startbox(self, memo): if self in memo: @@ -269,6 +271,7 @@ instnode = InstanceNode(box, escaped=False) self.nodes[box] = instnode self.first_escaping_op = False + instnode.known_length = op.args[1].getint() # XXX following guard_builtin will set the # correct class, otherwise it's a mess continue @@ -301,8 +304,6 @@ box = op.results[0] self.find_nodes_getfield(instnode, field, box) continue - else: - self.cleanup_fields(instnode) elif opname == 'setitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] @@ -311,8 +312,6 @@ self.find_nodes_setfield(instnode, field, self.getnode(op.args[3])) continue - else: - self.cleanup_fields(instnode) elif opname == 'guard_class': instnode = self.getnode(op.args[0]) if instnode.cls is None: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Sat Feb 14 12:20:58 2009 @@ -1,4 +1,5 @@ import py +py.test.skip("unsupported list ops") from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, hint From fijal at codespeak.net Sat Feb 14 12:44:10 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 12:44:10 +0100 (CET) Subject: [pypy-svn] r61873 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214114410.4EC0D168525@codespeak.net> Author: fijal Date: Sat Feb 14 12:44:08 2009 New Revision: 61873 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Introduce a special SpecNode for FixedClassList (unnecessary I think though), make sure that we reuse instance node when calling new_with_vtable or newlist Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 12:44:08 2009 @@ -4,6 +4,7 @@ operations_without_side_effects, operation_never_raises) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, + FixedListSpecNode, VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode, @@ -130,6 +131,8 @@ not self.expanded_fields): if self.cls is None: return NotSpecNode() + if isinstance(known_class, ListDescr): + return FixedListSpecNode(known_class) return FixedClassSpecNode(known_class) if not other.escaped: fields = [] @@ -304,6 +307,8 @@ box = op.results[0] self.find_nodes_getfield(instnode, field, box) continue + else: + instnode.escaped = True elif opname == 'setitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] @@ -312,6 +317,8 @@ self.find_nodes_setfield(instnode, field, self.getnode(op.args[3])) continue + else: + instnode.escaped = True elif opname == 'guard_class': instnode = self.getnode(op.args[0]) if instnode.cls is None: @@ -536,13 +543,18 @@ size = op.args[0].getint() key = instnode.cls.source.getint() type_cache.class_size[key] = size - continue + op = self.replace_arguments(op) + newoperations.append(op) + continue elif opname == 'newlist': instnode = self.nodes[op.results[0]] + assert isinstance(instnode.cls.source, ListDescr) if not instnode.escaped: instnode.virtual = True assert isinstance(instnode.cls.source, ListDescr) - continue + op = self.replace_arguments(op) + newoperations.append(op) + continue elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sat Feb 14 12:44:08 2009 @@ -58,6 +58,15 @@ return False return instnode.cls.source.equals(self.known_class) +class FixedListSpecNode(FixedClassSpecNode): + + def equals(self, other): + if type(other) is not FixedListSpecNode: + return False + else: + assert isinstance(other, FixedListSpecNode) # make annotator happy + return self.known_class.equals(other.known_class) + class SpecNodeWithFields(FixedClassSpecNode): def __init__(self, known_class, fields): FixedClassSpecNode.__init__(self, known_class) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sat Feb 14 12:44:08 2009 @@ -41,6 +41,25 @@ assert res == f(10) self.check_all_virtualized() + def test_cannot_be_virtual(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'l']) + def f(n): + l = [3] * 100 + while n > 0: + jitdriver.can_enter_jit(n=n, l=l) + jitdriver.jit_merge_point(n=n, l=l) + x = l[n] + l = [3] * 100 + l[3] = x + l[3] = x + 1 + n -= 1 + return l[0] + + res = self.meta_interp(f, [10]) + assert res == f(10) + # one setitem should be gone by now + self.check_loops(newlist=1, setitem=1, getitem=1) + def test_append_pop(self): py.test.skip("XXX") def f(n): From fijal at codespeak.net Sat Feb 14 12:51:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 12:51:23 +0100 (CET) Subject: [pypy-svn] r61874 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090214115123.6B14616851E@codespeak.net> Author: fijal Date: Sat Feb 14 12:51:20 2009 New Revision: 61874 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: A proper fix about guard_value Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 12:51:20 2009 @@ -516,8 +516,8 @@ continue exception_might_have_happened = False if opname == 'guard_value': - if (self.nodes[op.args[0]].const and - self.nodes[op.args[1]].const): + if (isinstance(self.nodes[op.args[0]].source, Const) and + isinstance(self.nodes[op.args[1]].source, Const)): continue op = self.optimize_guard(op) newoperations.append(op) From fijal at codespeak.net Sat Feb 14 12:59:39 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 12:59:39 +0100 (CET) Subject: [pypy-svn] r61875 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214115939.6616B168539@codespeak.net> Author: fijal Date: Sat Feb 14 12:59:39 2009 New Revision: 61875 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Log: a test and a fix Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 12:59:39 2009 @@ -309,6 +309,7 @@ continue else: instnode.escaped = True + self.first_escaping_op = False elif opname == 'setitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] @@ -319,6 +320,7 @@ continue else: instnode.escaped = True + self.first_escaping_op = False elif opname == 'guard_class': instnode = self.getnode(op.args[0]) if instnode.cls is None: @@ -527,6 +529,11 @@ ofs = op.args[1].getint() if self.optimize_getfield(instnode, ofs, op.results[0]): continue + # otherwise we need this getfield, but it does not + # invalidate caches + op = self.replace_arguments(op) + newoperations.append(op) + continue elif opname == 'getitem': instnode = self.nodes[op.args[1]] ofsbox = op.args[2] @@ -534,6 +541,10 @@ ofs = ofsbox.getint() if self.optimize_getfield(instnode, ofs, op.results[0]): continue + op = self.replace_arguments(op) + newoperations.append(op) + exception_might_have_happened = True + continue elif opname == 'new_with_vtable': # self.nodes[op.results[0]] keep the value from Steps (1,2) instnode = self.nodes[op.results[0]] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Sat Feb 14 12:59:39 2009 @@ -38,6 +38,26 @@ assert res == f(10) self.check_loops(setitem=2, getitem=1) + def test_list_escapes_but_getitem_goes(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) + def f(n): + l = [0] * (n + 1) + while n > 0: + myjitdriver.can_enter_jit(n=n, l=l) + myjitdriver.jit_merge_point(n=n, l=l) + x = l[0] + l[0] = x + 1 + l[n] = n + x = l[2] + y = l[1] + l[2] + l[1] = x + y + n -= 1 + return l[3] + + res = self.meta_interp(f, [10]) + assert res == f(10) + self.check_loops(setitem=3, getitem=3) + def test_list_indexerror(self): # this is an example where IndexError is raised before # even getting to the JIT From fijal at codespeak.net Sat Feb 14 13:31:57 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 13:31:57 +0100 (CET) Subject: [pypy-svn] r61876 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214123157.ABB44168512@codespeak.net> Author: fijal Date: Sat Feb 14 13:31:54 2009 New Revision: 61876 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Log: Fix stuff Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Sat Feb 14 13:31:54 2009 @@ -68,7 +68,7 @@ _prev = Box._extended_display try: Box._extended_display = False - for i, graph in enumerate(self.graphs): + for i, graph in enumerate(self.graphs[1:]): self.gengraph(graph, i) finally: Box._extended_display = _prev Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 13:31:54 2009 @@ -235,6 +235,11 @@ node = self.nodes[box] = InstanceNode(box, escaped=True) return node + def getsource(self, box): + if isinstance(box, Const): + return box + return self.nodes[box].source + def find_nodes_setfield(self, instnode, ofs, fieldnode): instnode.curfields[ofs] = fieldnode self.dependency_graph.append((instnode, fieldnode)) @@ -510,7 +515,9 @@ continue elif opname.startswith('guard_'): if opname == 'guard_true' or opname == 'guard_false': - if self.nodes[op.args[0]].const: + # XXX why we need that? + if (isinstance(self.nodes[op.args[0]].source, Const) or + self.nodes[op.args[0]].const): continue if (opname == 'guard_no_exception' or opname == 'guard_exception'): @@ -531,20 +538,13 @@ continue # otherwise we need this getfield, but it does not # invalidate caches - op = self.replace_arguments(op) - newoperations.append(op) - continue elif opname == 'getitem': instnode = self.nodes[op.args[1]] - ofsbox = op.args[2] + ofsbox = self.getsource(op.args[2]) if isinstance(ofsbox, ConstInt): ofs = ofsbox.getint() if self.optimize_getfield(instnode, ofs, op.results[0]): continue - op = self.replace_arguments(op) - newoperations.append(op) - exception_might_have_happened = True - continue elif opname == 'new_with_vtable': # self.nodes[op.results[0]] keep the value from Steps (1,2) instnode = self.nodes[op.results[0]] @@ -554,18 +554,14 @@ size = op.args[0].getint() key = instnode.cls.source.getint() type_cache.class_size[key] = size - op = self.replace_arguments(op) - newoperations.append(op) - continue + continue elif opname == 'newlist': instnode = self.nodes[op.results[0]] assert isinstance(instnode.cls.source, ListDescr) if not instnode.escaped: instnode.virtual = True assert isinstance(instnode.cls.source, ListDescr) - op = self.replace_arguments(op) - newoperations.append(op) - continue + continue elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] @@ -575,7 +571,7 @@ elif opname == 'setitem': instnode = self.nodes[op.args[1]] valuenode = self.getnode(op.args[3]) - ofsbox = op.args[2] + ofsbox = self.getsource(op.args[2]) if isinstance(ofsbox, ConstInt): ofs = ofsbox.getint() self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) @@ -608,7 +604,11 @@ self.nodes[box] = instnode continue elif opname not in operations_without_side_effects: - self.cleanup_field_caches(newoperations) + if opname not in ('getfield_gc', 'getitem', + 'setfield_gc', 'setitem'): + # those operations does not clean up caches, although + # they have side effects (at least set ones) + self.cleanup_field_caches(newoperations) if opname not in operation_never_raises: exception_might_have_happened = True for box in op.results: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Sat Feb 14 13:31:54 2009 @@ -36,7 +36,7 @@ res = self.meta_interp(f, [10]) assert res == f(10) - self.check_loops(setitem=2, getitem=1) + self.check_loops(setitem=2, getitem=0) def test_list_escapes_but_getitem_goes(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) @@ -56,7 +56,7 @@ res = self.meta_interp(f, [10]) assert res == f(10) - self.check_loops(setitem=3, getitem=3) + self.check_loops(setitem=3, getitem=2) def test_list_indexerror(self): # this is an example where IndexError is raised before From antocuni at codespeak.net Sat Feb 14 13:34:08 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 14 Feb 2009 13:34:08 +0100 (CET) Subject: [pypy-svn] r61877 - pypy/branch/oo-jit/pypy/translator/c Message-ID: <20090214123408.932EC168517@codespeak.net> Author: antocuni Date: Sat Feb 14 13:34:08 2009 New Revision: 61877 Modified: pypy/branch/oo-jit/pypy/translator/c/funcgen.py Log: this change belongs to r60900 Modified: pypy/branch/oo-jit/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/c/funcgen.py (original) +++ pypy/branch/oo-jit/pypy/translator/c/funcgen.py Sat Feb 14 13:34:08 2009 @@ -764,7 +764,7 @@ if isinstance(msg, Constant): msg = c_string_constant(''.join(msg.value.chars)) else: - msg = 'RPyString_AsString(%s)' % self.expr(msg) + msg = 'RPyString_AsCharP(%s)' % self.expr(msg) return 'fprintf(stderr, "%%s\\n", %s); abort();' % msg From fijal at codespeak.net Sat Feb 14 13:37:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 13:37:23 +0100 (CET) Subject: [pypy-svn] r61878 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214123723.DD26B168517@codespeak.net> Author: fijal Date: Sat Feb 14 13:37:23 2009 New Revision: 61878 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: Actually assert something about test_tl. Add a comment about missing case (simpler test please) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 13:37:23 2009 @@ -707,6 +707,9 @@ history.execute_and_record('setitem', [setfunc, box, ConstInt(ofs), itembox], 'void', False) + if storage.setitems: + # XXX this needs to check for exceptions somehow + # create guard_no_excpetion somehow newboxes = [] for index in storage.indices: if index < 0: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Sat Feb 14 13:37:23 2009 @@ -77,6 +77,12 @@ return interp_without_call(code, inputarg=inputarg) res = self.meta_interp(main, [1, 6]) + # we could eventually get away without setitems at all I think + # we're missing once guard_no_exception at the end I think + self.check_loops({'merge_point':1, 'guard_value':1, 'getitem':2, + 'setitem':4, 'guard_no_exception':2, 'int_mul':1, + 'int_sub':1, 'int_is_true':1, 'int_le':1, + 'guard_false':1}) assert res == 5040 From fijal at codespeak.net Sat Feb 14 13:38:28 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 13:38:28 +0100 (CET) Subject: [pypy-svn] r61879 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090214123828.18B55168517@codespeak.net> Author: fijal Date: Sat Feb 14 13:38:27 2009 New Revision: 61879 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: wuaaa, SyntaxError Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 13:38:27 2009 @@ -710,6 +710,7 @@ if storage.setitems: # XXX this needs to check for exceptions somehow # create guard_no_excpetion somehow + pass newboxes = [] for index in storage.indices: if index < 0: From fijal at codespeak.net Sat Feb 14 13:49:46 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 13:49:46 +0100 (CET) Subject: [pypy-svn] r61880 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp Message-ID: <20090214124946.86D0416853A@codespeak.net> Author: fijal Date: Sat Feb 14 13:49:43 2009 New Revision: 61880 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Log: * Don't support resizable lists (at all) * Fish a bit in the backend for correct type of ptr when having lists of pointers Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sat Feb 14 13:49:43 2009 @@ -85,7 +85,7 @@ 'strsetitem' : (('ptr', 'int', 'int'), None), 'getitem' : (('ptr', 'ptr', 'int'), 'int'), 'setitem' : (('ptr', 'ptr', 'int', 'int'), None), - 'newlist' : (('ptr', 'int'), 'ptr'), + 'newlist' : (('ptr', 'varargs'), 'ptr'), } # ____________________________________________________________ @@ -762,8 +762,19 @@ def op_setitem(self, ll_setitem, lst, item, val): self.do_call(ll_setitem, lst, item, val) - def op_newlist(self, ll_newlist, lgt): - return self.do_call(ll_newlist, lgt) + def op_newlist(self, ll_newlist, lgt, default_val=None): + res = self.do_call(ll_newlist, lgt) + if (default_val is not None and + isinstance(lltype.typeOf(default_val), lltype.Ptr)): + TP = lltype.typeOf(res).TO.OF + if default_val: + default_val = lltype.cast_opaque_ptr(TP, res) + else: + default_val = lltype.nullptr(TP.TO) + if default_val is not None: + for i in range(len(res)): + res[i] = default_val + return res def op_cast_int_to_ptr(self, i): if i == 0: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sat Feb 14 13:49:43 2009 @@ -609,7 +609,8 @@ c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper, oopspec_name, ll_args, op.result.concretetype) - if oopspec_name.startswith('list') or oopspec_name == 'newlist': + if ((oopspec_name.startswith('list') or oopspec_name == 'newlist') and + not isinstance(TP.TO, lltype.GcStruct)): if oopspec_name.startswith('list.getitem'): opname = oopspec_name[len('list.'):] elif oopspec_name.startswith('list.setitem'): From afa at codespeak.net Sat Feb 14 14:42:39 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 14 Feb 2009 14:42:39 +0100 (CET) Subject: [pypy-svn] r61881 - pypy/trunk/pypy/annotation Message-ID: <20090214134239.C80C416852A@codespeak.net> Author: afa Date: Sat Feb 14 14:42:37 2009 New Revision: 61881 Modified: pypy/trunk/pypy/annotation/bookkeeper.py Log: First step on supporting python2.6: since 2.6, instance methods also have a __self__ attribute, identical to im_self. Modified: pypy/trunk/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/trunk/pypy/annotation/bookkeeper.py (original) +++ pypy/trunk/pypy/annotation/bookkeeper.py Sat Feb 14 14:42:37 2009 @@ -415,17 +415,17 @@ elif isinstance(x, (ootype._record, ootype._string)): result = SomeOOInstance(ootype.typeOf(x)) elif callable(x): - if hasattr(x, '__self__') and x.__self__ is not None: + if hasattr(x, 'im_self') and hasattr(x, 'im_func'): + # on top of PyPy, for cases like 'l.append' where 'l' is a + # global constant list, the find_method() returns non-None + s_self = self.immutablevalue(x.im_self, need_const) + result = s_self.find_method(x.im_func.__name__) + elif hasattr(x, '__self__') and x.__self__ is not None: # for cases like 'l.append' where 'l' is a global constant list s_self = self.immutablevalue(x.__self__, need_const) result = s_self.find_method(x.__name__) if result is None: result = SomeObject() - elif hasattr(x, 'im_self') and hasattr(x, 'im_func'): - # on top of PyPy, for cases like 'l.append' where 'l' is a - # global constant list, the find_method() returns non-None - s_self = self.immutablevalue(x.im_self, need_const) - result = s_self.find_method(x.im_func.__name__) else: result = None if result is None: From fijal at codespeak.net Sat Feb 14 14:50:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 14:50:20 +0100 (CET) Subject: [pypy-svn] r61882 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214135020.CE2A7168524@codespeak.net> Author: fijal Date: Sat Feb 14 14:50:17 2009 New Revision: 61882 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: A bit break everything. Constant folding happening on earlier level allows us to detect really constant getitem from list, hence virtualizing it completely. on the other hand, we explode on some bug Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 14:50:17 2009 @@ -53,7 +53,9 @@ assert isinstance(ld, ListDescr) alloc_offset = len(self.list_allocations) malloc_func = ld.malloc_func - assert instnode.known_length != -1 + if instnode.known_length == -1: + # XXX + instnode.known_length = 42 self.list_allocations.append((malloc_func, instnode.known_length)) res = (alloc_offset + 1) << 16 @@ -92,9 +94,9 @@ self.source = source # a Box self.escaped = escaped self.startbox = startbox - self.const = const self.virtual = False self.virtualized = False + self.const = const self.cls = None self.origfields = {} self.curfields = {} @@ -182,11 +184,11 @@ def __repr__(self): flags = '' - if self.escaped: flags += 'e' - if self.startbox: flags += 's' - if self.const: flags += 'c' - if self.virtual: flags += 'v' - if self.virtualized: flags += 'V' + if self.escaped: flags += 'e' + if self.startbox: flags += 's' + if self.const: flags += 'c' + if self.virtual: flags += 'v' + if self.virtualized: flags += 'V' return "" % (self.source, flags) @@ -232,7 +234,8 @@ return self.nodes[box] except KeyError: assert isinstance(box, Const) - node = self.nodes[box] = InstanceNode(box, escaped=True) + node = self.nodes[box] = InstanceNode(box, escaped=True, + const=True) return node def getsource(self, box): @@ -307,8 +310,9 @@ elif opname == 'getitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] - if isinstance(fieldbox, ConstInt): - field = fieldbox.getint() + if (isinstance(fieldbox, ConstInt) or + self.nodes[op.args[2]].const): + field = self.getsource(fieldbox).getint() box = op.results[0] self.find_nodes_getfield(instnode, field, box) continue @@ -318,8 +322,9 @@ elif opname == 'setitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] - if isinstance(fieldbox, ConstInt): - field = fieldbox.getint() + if (isinstance(fieldbox, ConstInt) + or self.nodes[op.args[2]].const): + field = self.getsource(fieldbox).getint() self.find_nodes_setfield(instnode, field, self.getnode(op.args[3])) continue @@ -331,6 +336,11 @@ if instnode.cls is None: instnode.cls = InstanceNode(op.args[1]) continue + elif opname == 'guard_value': + instnode = self.getnode(op.args[0]) + assert isinstance(op.args[1], Const) + instnode.const = op.args[1] + continue elif opname == 'guard_nonvirtualized': instnode = self.getnode(op.args[0]) if instnode.startbox: @@ -338,8 +348,16 @@ if instnode.cls is None: instnode.cls = InstanceNode(op.args[1]) continue - elif (opname not in always_pure_operations and - opname not in operations_without_side_effects): + elif opname in always_pure_operations: + for arg in op.args: + if not self.getnode(arg).const: + break + else: + for box in op.results: + self.nodes[box] = InstanceNode(box, escaped=True, + const=True) + continue + elif opname not in operations_without_side_effects: # default case self.first_escaping_op = False for box in op.args: @@ -515,9 +533,7 @@ continue elif opname.startswith('guard_'): if opname == 'guard_true' or opname == 'guard_false': - # XXX why we need that? - if (isinstance(self.nodes[op.args[0]].source, Const) or - self.nodes[op.args[0]].const): + if self.nodes[op.args[0]].const: continue if (opname == 'guard_no_exception' or opname == 'guard_exception'): @@ -525,8 +541,8 @@ continue exception_might_have_happened = False if opname == 'guard_value': - if (isinstance(self.nodes[op.args[0]].source, Const) and - isinstance(self.nodes[op.args[1]].source, Const)): + if (self.nodes[op.args[0]].const and + self.nodes[op.args[1]].const): continue op = self.optimize_guard(op) newoperations.append(op) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sat Feb 14 14:50:17 2009 @@ -185,7 +185,7 @@ def extract_runtime_data(self, cpu, valuebox, resultlist): from pypy.jit.metainterp.codewriter import ListDescr - + resultlist.append(valuebox) ld = self.known_class assert isinstance(ld, ListDescr) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Sat Feb 14 14:50:17 2009 @@ -77,8 +77,7 @@ return interp_without_call(code, inputarg=inputarg) res = self.meta_interp(main, [1, 6]) - # we could eventually get away without setitems at all I think - # we're missing once guard_no_exception at the end I think + # eventually this loop should become really virtual self.check_loops({'merge_point':1, 'guard_value':1, 'getitem':2, 'setitem':4, 'guard_no_exception':2, 'int_mul':1, 'int_sub':1, 'int_is_true':1, 'int_le':1, From fijal at codespeak.net Sat Feb 14 14:59:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 14:59:23 +0100 (CET) Subject: [pypy-svn] r61883 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090214135923.3B5B6168535@codespeak.net> Author: fijal Date: Sat Feb 14 14:59:22 2009 New Revision: 61883 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: something is wrong, exploding assertion Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 14:59:22 2009 @@ -523,6 +523,8 @@ newoperations.append(op) continue elif opname == 'guard_builtin': + instnode = self.nodes[op.args[0]] + assert instnode.cls continue elif opname == 'guard_nonvirtualized': instnode = self.nodes[op.args[0]] From fijal at codespeak.net Sat Feb 14 15:08:34 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 15:08:34 +0100 (CET) Subject: [pypy-svn] r61884 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090214140834.08D14168529@codespeak.net> Author: fijal Date: Sat Feb 14 15:08:33 2009 New Revision: 61884 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: ARGH Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 15:08:33 2009 @@ -524,7 +524,8 @@ continue elif opname == 'guard_builtin': instnode = self.nodes[op.args[0]] - assert instnode.cls + if instnode.cls is None: + instnode.cls = InstanceNode(op.args[1]) continue elif opname == 'guard_nonvirtualized': instnode = self.nodes[op.args[0]] From fijal at codespeak.net Sat Feb 14 15:16:52 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 15:16:52 +0100 (CET) Subject: [pypy-svn] r61885 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090214141652.73091168531@codespeak.net> Author: fijal Date: Sat Feb 14 15:16:52 2009 New Revision: 61885 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Log: a failing test Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Sat Feb 14 15:16:52 2009 @@ -2,7 +2,7 @@ from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory from pypy.rpython.annlowlevel import llhelper from pypy.jit.metainterp.policy import StopAtXPolicy -from pypy.rlib.jit import JitDriver +from pypy.rlib.jit import JitDriver, hint from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR from pypy.jit.metainterp.test.test_vable_optimize import XY, xy_vtable @@ -83,7 +83,7 @@ return xy.x res = self.meta_interp(f, [18]) assert res == 10118 - self.check_loops(getfield_gc=0, setfield_gc=0) + self.check_loops(getfield_gc=0, setfield_gc=0) class ImplicitVirtualizableTests: @@ -116,6 +116,35 @@ assert res == 55 self.check_loops(getfield_gc=0, setfield_gc=0) + + def test_virtualizable_with_virtual_list(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'frame', 'x'], + virtualizables = ['frame']) + + + class Frame(object): + _virtualizable2_ = True + def __init__(self, l, s): + self.l = l + self.s = s + + def f(n): + frame = Frame([1,2,3,4], 0) + x = 0 + while n > 0: + myjitdriver.can_enter_jit(frame=frame, n=n, x=x) + myjitdriver.jit_merge_point(frame=frame, n=n, x=x) + frame.s = hint(frame.s, promote=True) + n -= 1 + x += frame.l[frame.s] + frame.s += 1 + x += frame.l[frame.s] + frame.s -= 1 + return x + + res = self.meta_interp(f, [10]) + assert res == f(10) + def test_external_read(self): py.test.skip("Fails") class Frame(object): From fijal at codespeak.net Sat Feb 14 15:53:31 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 15:53:31 +0100 (CET) Subject: [pypy-svn] r61886 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090214145331.1B87B168529@codespeak.net> Author: fijal Date: Sat Feb 14 15:53:29 2009 New Revision: 61886 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Constant folding seems to be a bit broken, think Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 15:53:29 2009 @@ -468,14 +468,13 @@ def optimize_getfield(self, instnode, ofs, box): if instnode.virtual or instnode.virtualized: - assert ofs in instnode.curfields # xxx - self.nodes[box] = instnode.curfields[ofs] + return True # this means field is never actually elif ofs in instnode.cleanfields: self.nodes[box] = instnode.cleanfields[ofs] + return True else: instnode.cleanfields[ofs] = InstanceNode(box) return False - return True def optimize_setfield(self, instnode, ofs, valuenode, valuebox): if instnode.virtual or instnode.virtualized: @@ -559,9 +558,10 @@ # invalidate caches elif opname == 'getitem': instnode = self.nodes[op.args[1]] - ofsbox = self.getsource(op.args[2]) - if isinstance(ofsbox, ConstInt): - ofs = ofsbox.getint() + ofsbox = op.args[2] + if (isinstance(ofsbox, ConstInt) or + self.nodes[ofsbox].const): + ofs = self.nodes[ofsbox].source.getint() if self.optimize_getfield(instnode, ofs, op.results[0]): continue elif opname == 'new_with_vtable': @@ -590,9 +590,10 @@ elif opname == 'setitem': instnode = self.nodes[op.args[1]] valuenode = self.getnode(op.args[3]) - ofsbox = self.getsource(op.args[2]) - if isinstance(ofsbox, ConstInt): - ofs = ofsbox.getint() + ofsbox = op.args[2] + if (isinstance(ofsbox, ConstInt) or + self.nodes[ofsbox].const): + ofs = self.nodes[ofsbox].source.getint() self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) continue elif opname == 'ooisnull' or opname == 'oononnull': @@ -614,7 +615,7 @@ op = self.replace_arguments(op) if opname in always_pure_operations: for box in op.args: - if isinstance(box, Box): + if isinstance(box, Box) and not self.nodes[box].const: break else: # all constant arguments: constant-fold away From fijal at codespeak.net Sat Feb 14 18:53:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 18:53:29 +0100 (CET) Subject: [pypy-svn] r61887 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214175329.C9B0816850A@codespeak.net> Author: fijal Date: Sat Feb 14 18:53:28 2009 New Revision: 61887 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: Fight with constant folding until it works. Now test_tl produces *really* good code Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 18:53:28 2009 @@ -68,7 +68,8 @@ num = self.deal_with_box(node.source, nodes, liveboxes, memo) if isinstance(instnode.cls.source, ListDescr): ld = instnode.cls.source - self.setitems.append((ld.setfunc, alloc_offset, ofs, num)) + x = (alloc_offset + 1) << 16 + self.setitems.append((ld.setfunc, x, ofs, num)) else: self.setfields.append((alloc_offset, ofs, num)) elif virtualized: @@ -91,6 +92,8 @@ class InstanceNode(object): def __init__(self, source, escaped=True, startbox=False, const=False): + if isinstance(source, Const): + assert const self.source = source # a Box self.escaped = escaped self.startbox = startbox @@ -138,7 +141,12 @@ return FixedClassSpecNode(known_class) if not other.escaped: fields = [] - lst = other.curfields.items() + if self is other: + d = other.curfields + d.update(self.origfields) + else: + d = other.curfields + lst = d.items() lst.sort() for ofs, node in lst: if ofs in self.origfields: @@ -273,7 +281,7 @@ if opname == 'new_with_vtable': box = op.results[0] instnode = InstanceNode(box, escaped=False) - instnode.cls = InstanceNode(op.args[1]) + instnode.cls = InstanceNode(op.args[1], const=True) self.nodes[box] = instnode self.first_escaping_op = False continue @@ -318,7 +326,6 @@ continue else: instnode.escaped = True - self.first_escaping_op = False elif opname == 'setitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] @@ -330,23 +337,23 @@ continue else: instnode.escaped = True - self.first_escaping_op = False elif opname == 'guard_class': instnode = self.getnode(op.args[0]) if instnode.cls is None: - instnode.cls = InstanceNode(op.args[1]) + instnode.cls = InstanceNode(op.args[1], const=True) continue elif opname == 'guard_value': instnode = self.getnode(op.args[0]) assert isinstance(op.args[1], Const) - instnode.const = op.args[1] + self.nodes[instnode.source] = InstanceNode(op.args[1], + const=True) continue elif opname == 'guard_nonvirtualized': instnode = self.getnode(op.args[0]) if instnode.startbox: instnode.virtualized = True if instnode.cls is None: - instnode.cls = InstanceNode(op.args[1]) + instnode.cls = InstanceNode(op.args[1], const=True) continue elif opname in always_pure_operations: for arg in op.args: @@ -354,7 +361,8 @@ break else: for box in op.results: - self.nodes[box] = InstanceNode(box, escaped=True, + self.nodes[box] = InstanceNode(box.constbox(), + escaped=True, const=True) continue elif opname not in operations_without_side_effects: @@ -468,6 +476,7 @@ def optimize_getfield(self, instnode, ofs, box): if instnode.virtual or instnode.virtualized: + assert ofs in instnode.curfields return True # this means field is never actually elif ofs in instnode.cleanfields: self.nodes[box] = instnode.cleanfields[ofs] @@ -558,10 +567,9 @@ # invalidate caches elif opname == 'getitem': instnode = self.nodes[op.args[1]] - ofsbox = op.args[2] - if (isinstance(ofsbox, ConstInt) or - self.nodes[ofsbox].const): - ofs = self.nodes[ofsbox].source.getint() + ofsbox = self.getsource(op.args[2]) + if isinstance(ofsbox, ConstInt): + ofs = ofsbox.getint() if self.optimize_getfield(instnode, ofs, op.results[0]): continue elif opname == 'new_with_vtable': @@ -590,17 +598,16 @@ elif opname == 'setitem': instnode = self.nodes[op.args[1]] valuenode = self.getnode(op.args[3]) - ofsbox = op.args[2] - if (isinstance(ofsbox, ConstInt) or - self.nodes[ofsbox].const): - ofs = self.nodes[ofsbox].source.getint() + ofsbox = self.getsource(op.args[2]) + if isinstance(ofsbox, ConstInt): + ofs = ofsbox.getint() self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) continue elif opname == 'ooisnull' or opname == 'oononnull': instnode = self.nodes[op.args[0]] if instnode.virtual: box = op.results[0] - instnode = InstanceNode(box, const=True) + instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue elif opname == 'oois' or opname == 'ooisnot': @@ -608,19 +615,19 @@ instnode_y = self.nodes[op.args[1]] if not instnode_x.virtual or not instnode_y.virtual: box = op.results[0] - instnode = InstanceNode(box, const=True) + instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue # default handling of arguments and return value(s) op = self.replace_arguments(op) if opname in always_pure_operations: for box in op.args: - if isinstance(box, Box) and not self.nodes[box].const: + if isinstance(box, Box): break else: # all constant arguments: constant-fold away for box in op.results: - instnode = InstanceNode(box.constbox()) + instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue elif opname not in operations_without_side_effects: @@ -687,17 +694,19 @@ new_instnode = self.nodes[jump_op.args[i]] old_specnode.adapt_to(new_instnode) -def box_from_index(allocated_boxes, boxes_from_frame, index): +def box_from_index(allocated_boxes, allocated_lists, + boxes_from_frame, index): if index < 0: return boxes_from_frame[~index] if index > 0xffff: - return allocated_boxes[(index - 1) >> 16] + return allocated_lists[(index - 1) >> 16] return allocated_boxes[index] def rebuild_boxes_from_guard_failure(guard_op, history, boxes_from_frame): allocated_boxes = [] allocated_lists = [] storage = guard_op.storage_info + for vtable in storage.allocations: sizebox = ConstInt(type_cache.class_size[vtable]) vtablebox = ConstInt(vtable) @@ -712,17 +721,17 @@ 'ptr', False) allocated_lists.append(listbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: - fieldbox = box_from_index(allocated_boxes, boxes_from_frame, - index_in_arglist) - box = box_from_index(allocated_boxes, boxes_from_frame, + fieldbox = box_from_index(allocated_boxes, allocated_lists, + boxes_from_frame, index_in_arglist) + box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) history.execute_and_record('setfield_gc', [box, ConstInt(ofs), fieldbox], 'void', False) for setfunc, index_in_alloc, ofs, index_in_arglist in storage.setitems: - itembox = box_from_index(allocated_boxes, boxes_from_frame, - index_in_arglist) - box = box_from_index(allocated_lists, boxes_from_frame, + itembox = box_from_index(allocated_boxes, allocated_lists, + boxes_from_frame, index_in_arglist) + box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, index_in_alloc) history.execute_and_record('setitem', [setfunc, box, ConstInt(ofs), itembox], Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Sat Feb 14 18:53:28 2009 @@ -78,8 +78,8 @@ res = self.meta_interp(main, [1, 6]) # eventually this loop should become really virtual - self.check_loops({'merge_point':1, 'guard_value':1, 'getitem':2, - 'setitem':4, 'guard_no_exception':2, 'int_mul':1, + self.check_loops({'merge_point':1, + 'int_mul':1, 'jump':1, 'int_sub':1, 'int_is_true':1, 'int_le':1, 'guard_false':1}) assert res == 5040 From fijal at codespeak.net Sat Feb 14 19:13:00 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 19:13:00 +0100 (CET) Subject: [pypy-svn] r61888 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090214181300.CBC9416850D@codespeak.net> Author: fijal Date: Sat Feb 14 19:13:00 2009 New Revision: 61888 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Log: guard_excpetion is not necesarilly always pure operation. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Sat Feb 14 19:13:00 2009 @@ -68,7 +68,11 @@ _prev = Box._extended_display try: Box._extended_display = False - for i, graph in enumerate(self.graphs[1:]): + if len(self.graphs) > 1: + graphs = self.graphs[1:] + else: + graphs = self.graphs + for i, graph in enumerate(graphs): self.gengraph(graph, i) finally: Box._extended_display = _prev Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Sat Feb 14 19:13:00 2009 @@ -84,7 +84,7 @@ always_pure_operations = {} operation_never_raises = {} -for guard in ['guard_no_exception', 'guard_exception', 'guard_true', +for guard in ['guard_no_exception', 'guard_true', 'guard_false', 'guard_value', 'guard_class']: always_pure_operations[guard] = True operation_never_raises[guard] = True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sat Feb 14 19:13:00 2009 @@ -274,7 +274,8 @@ # Steps (1) and (2) self.first_escaping_op = True for box in self.loop.operations[0].args: - self.nodes[box] = InstanceNode(box, escaped=False, startbox=True) + self.nodes[box] = InstanceNode(box, escaped=False, startbox=True, + const=isinstance(box, Const)) for op in self.loop.operations[1:-1]: opname = op.opname Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sat Feb 14 19:13:00 2009 @@ -42,7 +42,7 @@ from pypy.jit.metainterp.optimize import InstanceNode if instnode.cls is None: - instnode.cls = InstanceNode(self.known_class) + instnode.cls = InstanceNode(self.known_class, const=True) else: assert instnode.cls.source.equals(self.known_class) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Sat Feb 14 19:13:00 2009 @@ -56,7 +56,7 @@ res = self.meta_interp(f, [10]) assert res == f(10) - self.check_loops(setitem=3, getitem=2) + self.check_loops(setitem=3, getitem=0) def test_list_indexerror(self): # this is an example where IndexError is raised before Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Sat Feb 14 19:13:00 2009 @@ -74,6 +74,7 @@ return e.n def f(n): return a(n) + res = self.interp_operations(f, [-4]) assert res == -40 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Sat Feb 14 19:13:00 2009 @@ -44,6 +44,7 @@ assert res == 42 def test_accumulator(self): + py.test.skip("bugs") path = py.path.local(tlc.__file__).dirpath('accumulator.tlc.src') code = path.read() res = self.exec_code(code, 20) From fijal at codespeak.net Sat Feb 14 19:19:53 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 14 Feb 2009 19:19:53 +0100 (CET) Subject: [pypy-svn] r61889 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090214181953.2B37E168510@codespeak.net> Author: fijal Date: Sat Feb 14 19:19:52 2009 New Revision: 61889 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Log: comment out those changes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Sat Feb 14 19:19:52 2009 @@ -68,10 +68,10 @@ _prev = Box._extended_display try: Box._extended_display = False - if len(self.graphs) > 1: - graphs = self.graphs[1:] - else: - graphs = self.graphs + #if len(self.graphs) > 1: + # graphs = self.graphs[1:] + #else: + graphs = self.graphs for i, graph in enumerate(graphs): self.gengraph(graph, i) finally: From getxsick at codespeak.net Sat Feb 14 22:09:09 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sat, 14 Feb 2009 22:09:09 +0100 (CET) Subject: [pypy-svn] r61890 - pypy/trunk/pypy/lib Message-ID: <20090214210909.E29A31684EB@codespeak.net> Author: getxsick Date: Sat Feb 14 22:09:08 2009 New Revision: 61890 Modified: pypy/trunk/pypy/lib/_locale.py Log: (jlg, getxsick) logical error in type checking Modified: pypy/trunk/pypy/lib/_locale.py ============================================================================== --- pypy/trunk/pypy/lib/_locale.py (original) +++ pypy/trunk/pypy/lib/_locale.py Sat Feb 14 22:09:08 2009 @@ -260,7 +260,7 @@ return _strcoll(s1, s2) # If neither argument is unicode, it's an error. - if not isinstance(s1, unicode) and isinstance(s2, unicode): + if not isinstance(s1, unicode) or not isinstance(s2, unicode): raise ValueError("strcoll arguments must be strings") # Convert the non-unicode argument to unicode. From getxsick at codespeak.net Sat Feb 14 22:45:50 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sat, 14 Feb 2009 22:45:50 +0100 (CET) Subject: [pypy-svn] r61891 - pypy/trunk/pypy/lib Message-ID: <20090214214550.74D051684F0@codespeak.net> Author: getxsick Date: Sat Feb 14 22:45:49 2009 New Revision: 61891 Modified: pypy/trunk/pypy/lib/_locale.py Log: (jlg, getxsick) ops. r61890 fix was broken. fix for the fix tho. Modified: pypy/trunk/pypy/lib/_locale.py ============================================================================== --- pypy/trunk/pypy/lib/_locale.py (original) +++ pypy/trunk/pypy/lib/_locale.py Sat Feb 14 22:45:49 2009 @@ -260,7 +260,7 @@ return _strcoll(s1, s2) # If neither argument is unicode, it's an error. - if not isinstance(s1, unicode) or not isinstance(s2, unicode): + if not isinstance(s1, unicode) and not isinstance(s2, unicode): raise ValueError("strcoll arguments must be strings") # Convert the non-unicode argument to unicode. From afa at codespeak.net Sat Feb 14 23:36:55 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 14 Feb 2009 23:36:55 +0100 (CET) Subject: [pypy-svn] r61894 - in pypy/trunk/pypy/rpython: . lltypesystem Message-ID: <20090214223655.791CF1684ED@codespeak.net> Author: afa Date: Sat Feb 14 23:36:53 2009 New Revision: 61894 Modified: pypy/trunk/pypy/rpython/annlowlevel.py pypy/trunk/pypy/rpython/lltypesystem/rffi.py Log: Not a real change, just indent the code in a "if 1:" block before I turn it into a function which returns similar objects for str and unicode. Modified: pypy/trunk/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/trunk/pypy/rpython/annlowlevel.py (original) +++ pypy/trunk/pypy/rpython/annlowlevel.py Sat Feb 14 23:36:53 2009 @@ -381,46 +381,47 @@ # ____________________________________________________________ -def hlstr(ll_s): - if hasattr(ll_s, 'chars'): - return ''.join(ll_s.chars) - else: - return ll_s._str - -class HLStrEntry(extregistry.ExtRegistryEntry): - _about_ = hlstr - - def compute_result_annotation(self, s_ll_str): - return annmodel.SomeString() - - def specialize_call(self, hop): - hop.exception_cannot_occur() - assert hop.args_r[0].lowleveltype == hop.r_result.lowleveltype - v_ll_str, = hop.inputargs(*hop.args_r) - return hop.genop('same_as', [v_ll_str], - resulttype = hop.r_result.lowleveltype) - -def llstr(s): - from pypy.rpython.lltypesystem.rstr import mallocstr - # XXX not sure what to do with ootypesystem - ll_s = mallocstr(len(s)) - for i, c in enumerate(s): - ll_s.chars[i] = c - return ll_s - -class LLStrEntry(extregistry.ExtRegistryEntry): - _about_ = llstr - - def compute_result_annotation(self, s_str): - from pypy.rpython.lltypesystem.rstr import STR - return annmodel.lltype_to_annotation(lltype.Ptr(STR)) - - def specialize_call(self, hop): - hop.exception_cannot_occur() - assert hop.args_r[0].lowleveltype == hop.r_result.lowleveltype - v_ll_str, = hop.inputargs(*hop.args_r) - return hop.genop('same_as', [v_ll_str], - resulttype = hop.r_result.lowleveltype) +if 1: + def hlstr(ll_s): + if hasattr(ll_s, 'chars'): + return ''.join(ll_s.chars) + else: + return ll_s._str + + class HLStrEntry(extregistry.ExtRegistryEntry): + _about_ = hlstr + + def compute_result_annotation(self, s_ll_str): + return annmodel.SomeString() + + def specialize_call(self, hop): + hop.exception_cannot_occur() + assert hop.args_r[0].lowleveltype == hop.r_result.lowleveltype + v_ll_str, = hop.inputargs(*hop.args_r) + return hop.genop('same_as', [v_ll_str], + resulttype = hop.r_result.lowleveltype) + + def llstr(s): + from pypy.rpython.lltypesystem.rstr import mallocstr + # XXX not sure what to do with ootypesystem + ll_s = mallocstr(len(s)) + for i, c in enumerate(s): + ll_s.chars[i] = c + return ll_s + + class LLStrEntry(extregistry.ExtRegistryEntry): + _about_ = llstr + + def compute_result_annotation(self, s_str): + from pypy.rpython.lltypesystem.rstr import STR + return annmodel.lltype_to_annotation(lltype.Ptr(STR)) + + def specialize_call(self, hop): + hop.exception_cannot_occur() + assert hop.args_r[0].lowleveltype == hop.r_result.lowleveltype + v_ll_str, = hop.inputargs(*hop.args_r) + return hop.genop('same_as', [v_ll_str], + resulttype = hop.r_result.lowleveltype) # ____________________________________________________________ Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rffi.py Sat Feb 14 23:36:53 2009 @@ -495,132 +495,134 @@ FLOATP = lltype.Ptr(lltype.Array(FLOAT, hints={'nolength': True})) # various type mapping -# str -> char* -def str2charp(s): - """ str -> char* - """ - array = lltype.malloc(CCHARP.TO, len(s) + 1, flavor='raw') - for i in range(len(s)): - array[i] = s[i] - array[len(s)] = '\x00' - return array -str2charp._annenforceargs_ = [str] - -def free_charp(cp): - lltype.free(cp, flavor='raw') - -# char* -> str -# doesn't free char* -def charp2str(cp): - l = [] - i = 0 - while cp[i] != '\x00': - l.append(cp[i]) - i += 1 - return "".join(l) - -# str -> char* -def get_nonmovingbuffer(data): - """ - Either returns a non-moving copy or performs neccessary pointer arithmetic - to return a pointer to the characters of a string if the string is already - nonmovable. - Must be followed by a free_nonmovingbuffer call. - """ - if rgc.can_move(data): - count = len(data) - buf = lltype.malloc(CCHARP.TO, count, flavor='raw') - for i in range(count): - buf[i] = data[i] - return buf - else: - data_start = cast_ptr_to_adr(llstr(data)) + \ - offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - return cast(CCHARP, data_start) - -# (str, char*) -> None -def free_nonmovingbuffer(data, buf): - """ - Either free a non-moving buffer or keep the original storage alive. - """ - if rgc.can_move(data): - lltype.free(buf, flavor='raw') - else: - keepalive_until_here(data) - -# int -> (char*, str) -def alloc_buffer(count): - """ - Returns a (raw_buffer, gc_buffer) pair, allocated with count bytes. - The raw_buffer can be safely passed to a native function which expects it - to not move. Call str_from_buffer with the returned values to get a safe - high-level string. When the garbage collector cooperates, this allows for - the process to be performed without an extra copy. - Make sure to call keep_buffer_alive_until_here on the returned values. - """ - str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - gc_buf = rgc.malloc_nonmovable(STR, count) - if gc_buf: - realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset - raw_buf = cast(CCHARP, realbuf) - return raw_buf, gc_buf - else: - raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') - return raw_buf, lltype.nullptr(STR) -alloc_buffer._always_inline_ = True # to get rid of the returned tuple obj +if 1: + # str -> char* + def str2charp(s): + """ str -> char* + """ + array = lltype.malloc(CCHARP.TO, len(s) + 1, flavor='raw') + for i in range(len(s)): + array[i] = s[i] + array[len(s)] = '\x00' + return array + str2charp._annenforceargs_ = [str] + + def free_charp(cp): + lltype.free(cp, flavor='raw') + + # char* -> str + # doesn't free char* + def charp2str(cp): + l = [] + i = 0 + while cp[i] != '\x00': + l.append(cp[i]) + i += 1 + return "".join(l) + + # str -> char* + def get_nonmovingbuffer(data): + """ + Either returns a non-moving copy or performs neccessary pointer + arithmetic to return a pointer to the characters of a string if the + string is already nonmovable. + Must be followed by a free_nonmovingbuffer call. + """ + if rgc.can_move(data): + count = len(data) + buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + for i in range(count): + buf[i] = data[i] + return buf + else: + data_start = cast_ptr_to_adr(llstr(data)) + \ + offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + return cast(CCHARP, data_start) + + # (str, char*) -> None + def free_nonmovingbuffer(data, buf): + """ + Either free a non-moving buffer or keep the original storage alive. + """ + if rgc.can_move(data): + lltype.free(buf, flavor='raw') + else: + keepalive_until_here(data) -# (char*, str, int, int) -> None -def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): - """ - Converts from a pair returned by alloc_buffer to a high-level string. - The returned string will be truncated to needed_size. - """ - assert allocated_size >= needed_size - - if gc_buf and (allocated_size == needed_size): - return hlstr(gc_buf) - - new_buf = lltype.malloc(STR, needed_size) - try: + # int -> (char*, str) + def alloc_buffer(count): + """ + Returns a (raw_buffer, gc_buffer) pair, allocated with count bytes. The + raw_buffer can be safely passed to a native function which expects it to + not move. Call str_from_buffer with the returned values to get a safe + high-level string. When the garbage collector cooperates, this allows + for the process to be performed without an extra copy. + Make sure to call keep_buffer_alive_until_here on the returned values. + """ str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + gc_buf = rgc.malloc_nonmovable(STR, count) if gc_buf: - src = cast_ptr_to_adr(gc_buf) + str_chars_offset + realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset + raw_buf = cast(CCHARP, realbuf) + return raw_buf, gc_buf else: - src = cast_ptr_to_adr(raw_buf) + itemoffsetof(CCHARP.TO, 0) - dest = cast_ptr_to_adr(new_buf) + str_chars_offset - ## FIXME: This is bad, because dest could potentially move - ## if there are threads involved. - raw_memcopy(src, dest, - llmemory.sizeof(lltype.Char) * needed_size) - return hlstr(new_buf) - finally: - keepalive_until_here(new_buf) - -# (char*, str) -> None -def keep_buffer_alive_until_here(raw_buf, gc_buf): - """ - Keeps buffers alive or frees temporary buffers created by alloc_buffer. - This must be called after a call to alloc_buffer, usually in a try/finally - block. - """ - if gc_buf: - keepalive_until_here(gc_buf) - elif raw_buf: - lltype.free(raw_buf, flavor='raw') - -# char* -> str, with an upper bound on the length in case there is no \x00 -def charp2strn(cp, maxlen): - l = [] - i = 0 - while i < maxlen and cp[i] != '\x00': - l.append(cp[i]) - i += 1 - return "".join(l) - -# char* and size -> str (which can contain null bytes) -def charpsize2str(cp, size): - l = [cp[i] for i in range(size)] - return "".join(l) + raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + return raw_buf, lltype.nullptr(STR) + alloc_buffer._always_inline_ = True # to get rid of the returned tuple obj + + # (char*, str, int, int) -> None + def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): + """ + Converts from a pair returned by alloc_buffer to a high-level string. + The returned string will be truncated to needed_size. + """ + assert allocated_size >= needed_size + + if gc_buf and (allocated_size == needed_size): + return hlstr(gc_buf) + + new_buf = lltype.malloc(STR, needed_size) + try: + str_chars_offset = (offsetof(STR, 'chars') + + itemoffsetof(STR.chars, 0)) + if gc_buf: + src = cast_ptr_to_adr(gc_buf) + str_chars_offset + else: + src = cast_ptr_to_adr(raw_buf) + itemoffsetof(CCHARP.TO, 0) + dest = cast_ptr_to_adr(new_buf) + str_chars_offset + ## FIXME: This is bad, because dest could potentially move + ## if there are threads involved. + raw_memcopy(src, dest, + llmemory.sizeof(lltype.Char) * needed_size) + return hlstr(new_buf) + finally: + keepalive_until_here(new_buf) + + # (char*, str) -> None + def keep_buffer_alive_until_here(raw_buf, gc_buf): + """ + Keeps buffers alive or frees temporary buffers created by alloc_buffer. + This must be called after a call to alloc_buffer, usually in a + try/finally block. + """ + if gc_buf: + keepalive_until_here(gc_buf) + elif raw_buf: + lltype.free(raw_buf, flavor='raw') + + # char* -> str, with an upper bound on the length in case there is no \x00 + def charp2strn(cp, maxlen): + l = [] + i = 0 + while i < maxlen and cp[i] != '\x00': + l.append(cp[i]) + i += 1 + return "".join(l) + + # char* and size -> str (which can contain null bytes) + def charpsize2str(cp, size): + l = [cp[i] for i in range(size)] + return "".join(l) # char** CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True})) From jlg at codespeak.net Sat Feb 14 23:37:12 2009 From: jlg at codespeak.net (jlg at codespeak.net) Date: Sat, 14 Feb 2009 23:37:12 +0100 (CET) Subject: [pypy-svn] r61895 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090214223712.A590D1684EE@codespeak.net> Author: jlg Date: Sat Feb 14 23:37:11 2009 New Revision: 61895 Modified: pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (getxsick, jlg) strcoll partially implemented, does not work with unicode arguments - rffi.uniocode2wcharp() needed Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Sat Feb 14 23:37:11 2009 @@ -7,7 +7,7 @@ #'lconv': 'interp_locale.lconv', 'setlocale': 'interp_locale.setlocale', 'localeconv': 'interp_locale.localeconv', - #'strcoll': 'interp_locale.strcoll', + 'strcoll': 'interp_locale.strcoll', #'strxfrm': 'interp_locale.strxfrm', #'getdefaultlocale': 'interp_locale.getdefaultlocale', #'gettext': 'interp_locale.gettext', Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sat Feb 14 23:37:11 2009 @@ -163,3 +163,32 @@ localeconv.unwrap_spec = [ObjSpace] +_strcoll = external('strcoll', [rffi.CCHARP, rffi.CCHARP], rffi.INT) +_wcscoll = external('wcscoll', [rffi.WCHAR_TP, rffi.WCHAR_TP], rffi.INT) + +def strcoll(space, w_s1, w_s2): + "string,string -> int. Compares two strings according to the locale." + + if space.is_true(space.isinstance(w_s1, space.w_str)) and \ + space.is_true(space.isinstance(w_s2, space.w_str)): + + s1, s2 = space.str_w(w_s1), space.str_w(w_s2) + return space.wrap(_strcoll(rffi.str2charp(s1), rffi.str2charp(s2))) + + #if not space.is_true(space.isinstance(w_s1, space.w_unicode)) and \ + # not space.is_true(space.isinstance(w_s2, space.w_unicode)): + # raise OperationError(space.w_ValueError, + # space.wrap("strcoll arguments must be strings")) + + s1, s2 = space.unicode_w(w_s1), space.unicode_w(w_s2) + + # XXX rffi.unicode2wcharp needed + raise OperationError(space.w_NotImplementedError, + space.wrap("PyPy specific - not implemented for unicode arguments")) + + #s1_c = rffi.str2charp(s1) + #s2_c = rffi.str2charp(s2) + #return space.wrap(_wcscoll(s1_c, s2_c)) + +strcoll.unwrap_spec = [ObjSpace, W_Root, W_Root] + Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sat Feb 14 23:37:11 2009 @@ -92,6 +92,33 @@ for k, v in lconv_c.items(): assert lconv[k] == v + def test_strcoll(self): + import _locale + + _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") + assert _locale.strcoll("a", "b") < 0 + assert _locale.strcoll('\xc4\x85', "b") < 0 + + assert _locale.strcoll('\xc4\x87', "b") > 0 + assert _locale.strcoll("c", "b") > 0 + + assert _locale.strcoll("b", "b") == 0 + + raises(TypeError, _locale.strcoll, 1, "b") + raises(TypeError, _locale.strcoll, "b", 1) + + def test_strcoll_unicode(self): + skip("not implemented, rffi.unicode2wcharp needed") + import _locale + + _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") + assert _locale.strcoll(u"b", u"b") == 0 + assert _locale.strcoll(u'\xc4\x85', "b") < 0 + assert _locale.strcoll(u'\xc4\x87', "b") > 0 + + raises(TypeError, _locale.strcoll, 1, u"b") + raises(TypeError, _locale.strcoll, u"b", 1) + def test_str_float(self): import _locale import locale From afa at codespeak.net Sat Feb 14 23:42:29 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 14 Feb 2009 23:42:29 +0100 (CET) Subject: [pypy-svn] r61896 - in pypy/trunk/pypy/rpython: . test Message-ID: <20090214224229.7A6931684E8@codespeak.net> Author: afa Date: Sat Feb 14 23:42:28 2009 New Revision: 61896 Modified: pypy/trunk/pypy/rpython/annlowlevel.py pypy/trunk/pypy/rpython/test/test_annlowlevel.py Log: Annotation helpers for unicode strings. Modified: pypy/trunk/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/trunk/pypy/rpython/annlowlevel.py (original) +++ pypy/trunk/pypy/rpython/annlowlevel.py Sat Feb 14 23:42:28 2009 @@ -381,10 +381,15 @@ # ____________________________________________________________ -if 1: +def make_string_entries(strtype): + assert strtype in (str, unicode) + def hlstr(ll_s): if hasattr(ll_s, 'chars'): - return ''.join(ll_s.chars) + if strtype is str: + return ''.join(ll_s.chars) + else: + return u''.join(ll_s.chars) else: return ll_s._str @@ -392,7 +397,10 @@ _about_ = hlstr def compute_result_annotation(self, s_ll_str): - return annmodel.SomeString() + if strtype is str: + return annmodel.SomeString() + else: + return annmodel.SomeUnicodeString() def specialize_call(self, hop): hop.exception_cannot_occur() @@ -402,9 +410,12 @@ resulttype = hop.r_result.lowleveltype) def llstr(s): - from pypy.rpython.lltypesystem.rstr import mallocstr + from pypy.rpython.lltypesystem.rstr import mallocstr, mallocunicode # XXX not sure what to do with ootypesystem - ll_s = mallocstr(len(s)) + if strtype is str: + ll_s = mallocstr(len(s)) + else: + ll_s = mallocunicode(len(s)) for i, c in enumerate(s): ll_s.chars[i] = c return ll_s @@ -413,8 +424,11 @@ _about_ = llstr def compute_result_annotation(self, s_str): - from pypy.rpython.lltypesystem.rstr import STR - return annmodel.lltype_to_annotation(lltype.Ptr(STR)) + from pypy.rpython.lltypesystem.rstr import STR, UNICODE + if strtype is str: + return annmodel.lltype_to_annotation(lltype.Ptr(STR)) + else: + return annmodel.lltype_to_annotation(lltype.Ptr(UNICODE)) def specialize_call(self, hop): hop.exception_cannot_occur() @@ -423,6 +437,11 @@ return hop.genop('same_as', [v_ll_str], resulttype = hop.r_result.lowleveltype) + return hlstr, llstr + +hlstr, llstr = make_string_entries(str) +hlunicode, llunicode = make_string_entries(unicode) + # ____________________________________________________________ def cast_object_to_ptr(PTR, object): Modified: pypy/trunk/pypy/rpython/test/test_annlowlevel.py ============================================================================== --- pypy/trunk/pypy/rpython/test/test_annlowlevel.py (original) +++ pypy/trunk/pypy/rpython/test/test_annlowlevel.py Sat Feb 14 23:42:28 2009 @@ -3,8 +3,9 @@ """ from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin -from pypy.rpython.lltypesystem.rstr import mallocstr +from pypy.rpython.lltypesystem.rstr import mallocstr, mallocunicode from pypy.rpython.annlowlevel import hlstr, llstr +from pypy.rpython.annlowlevel import hlunicode, llunicode class TestLLType(BaseRtypingTest, LLRtypeMixin): def test_hlstr(self): @@ -29,3 +30,24 @@ res = self.interpret(f, [self.string_to_ll("abc")]) assert res == 3 + def test_hlunicode(self): + s = mallocunicode(3) + s.chars[0] = u"a" + s.chars[1] = u"b" + s.chars[2] = u"c" + assert hlunicode(s) == u"abc" + + def test_llunicode(self): + s = llunicode(u"abc") + assert len(s.chars) == 3 + assert s.chars[0] == u"a" + assert s.chars[1] == u"b" + assert s.chars[2] == u"c" + + def test_llunicode_compile(self): + def f(arg): + s = llunicode(hlunicode(arg)) + return len(s.chars) + + res = self.interpret(f, [self.unicode_to_ll(u"abc")]) + assert res == 3 From afa at codespeak.net Sun Feb 15 00:05:22 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 15 Feb 2009 00:05:22 +0100 (CET) Subject: [pypy-svn] r61898 - in pypy/trunk/pypy/rpython/lltypesystem: . test Message-ID: <20090214230522.1EE461684E8@codespeak.net> Author: afa Date: Sun Feb 15 00:05:21 2009 New Revision: 61898 Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Log: Support for unicode in rffi: rffi.CWCHARP Most functions available for [r]strings now have their [r]unicode version: allocation, conversion from/to wcharp, nonmoving buffers. Modified: pypy/trunk/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rffi.py Sun Feb 15 00:05:21 2009 @@ -15,8 +15,7 @@ from pypy.rpython.tool.rfficache import platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.backendopt.canraise import RaiseAnalyzer -from pypy.rpython.annlowlevel import llhelper, llstr, hlstr -from pypy.rpython.lltypesystem.rstr import STR +from pypy.rpython.annlowlevel import llhelper from pypy.rlib.objectmodel import we_are_translated from pypy.rpython.lltypesystem import llmemory import os, sys @@ -485,6 +484,9 @@ # char * CCHARP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True})) +# wchar_t * +CWCHARP = lltype.Ptr(lltype.Array(lltype.UniChar, hints={'nolength': True})) + # int *, unsigned int *, etc. #INTP = ... see setup() above @@ -495,17 +497,39 @@ FLOATP = lltype.Ptr(lltype.Array(FLOAT, hints={'nolength': True})) # various type mapping -if 1: + +# conversions between str and char* +# conversions between unicode and wchar_t* +def make_string_mappings(strtype): + + if strtype is str: + from pypy.rpython.lltypesystem.rstr import UNICODE as STRTYPE + from pypy.rpython.annlowlevel import llstr as llstrtype + from pypy.rpython.annlowlevel import hlstr as hlstrtype + from pypy.rpython.lltypesystem.rstr import STR as STRTYPE + TYPEP = CCHARP + ll_char_type = lltype.Char + emptystr = '' + lastchar = '\x00' + else: + from pypy.rpython.lltypesystem.rstr import UNICODE as STRTYPE + from pypy.rpython.annlowlevel import llunicode as llstrtype + from pypy.rpython.annlowlevel import hlunicode as hlstrtype + TYPEP = CWCHARP + ll_char_type = lltype.UniChar + emptystr = u'' + lastchar = u'\x00' + # str -> char* def str2charp(s): """ str -> char* """ - array = lltype.malloc(CCHARP.TO, len(s) + 1, flavor='raw') + array = lltype.malloc(TYPEP.TO, len(s) + 1, flavor='raw') for i in range(len(s)): array[i] = s[i] - array[len(s)] = '\x00' + array[len(s)] = lastchar return array - str2charp._annenforceargs_ = [str] + str2charp._annenforceargs_ = [strtype] def free_charp(cp): lltype.free(cp, flavor='raw') @@ -515,29 +539,29 @@ def charp2str(cp): l = [] i = 0 - while cp[i] != '\x00': + while cp[i] != lastchar: l.append(cp[i]) i += 1 - return "".join(l) + return emptystr.join(l) # str -> char* def get_nonmovingbuffer(data): """ Either returns a non-moving copy or performs neccessary pointer arithmetic to return a pointer to the characters of a string if the - string is already nonmovable. - Must be followed by a free_nonmovingbuffer call. + string is already nonmovable. Must be followed by a + free_nonmovingbuffer call. """ if rgc.can_move(data): count = len(data) - buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + buf = lltype.malloc(TYPEP.TO, count, flavor='raw') for i in range(count): buf[i] = data[i] return buf else: - data_start = cast_ptr_to_adr(llstr(data)) + \ - offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - return cast(CCHARP, data_start) + data_start = cast_ptr_to_adr(llstrtype(data)) + \ + offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0) + return cast(TYPEP, data_start) # (str, char*) -> None def free_nonmovingbuffer(data, buf): @@ -552,23 +576,24 @@ # int -> (char*, str) def alloc_buffer(count): """ - Returns a (raw_buffer, gc_buffer) pair, allocated with count bytes. The - raw_buffer can be safely passed to a native function which expects it to - not move. Call str_from_buffer with the returned values to get a safe - high-level string. When the garbage collector cooperates, this allows - for the process to be performed without an extra copy. + Returns a (raw_buffer, gc_buffer) pair, allocated with count bytes. + The raw_buffer can be safely passed to a native function which expects + it to not move. Call str_from_buffer with the returned values to get a + safe high-level string. When the garbage collector cooperates, this + allows for the process to be performed without an extra copy. Make sure to call keep_buffer_alive_until_here on the returned values. """ - str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) - gc_buf = rgc.malloc_nonmovable(STR, count) + str_chars_offset = (offsetof(STRTYPE, 'chars') + \ + itemoffsetof(STRTYPE.chars, 0)) + gc_buf = rgc.malloc_nonmovable(STRTYPE, count) if gc_buf: realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset - raw_buf = cast(CCHARP, realbuf) + raw_buf = cast(TYPEP, realbuf) return raw_buf, gc_buf else: - raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') - return raw_buf, lltype.nullptr(STR) - alloc_buffer._always_inline_ = True # to get rid of the returned tuple obj + raw_buf = lltype.malloc(TYPEP.TO, count, flavor='raw') + return raw_buf, lltype.nullptr(STRTYPE) + alloc_buffer._always_inline_ = True # to get rid of the returned tuple # (char*, str, int, int) -> None def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): @@ -579,22 +604,22 @@ assert allocated_size >= needed_size if gc_buf and (allocated_size == needed_size): - return hlstr(gc_buf) + return hlstrtype(gc_buf) - new_buf = lltype.malloc(STR, needed_size) + new_buf = lltype.malloc(STRTYPE, needed_size) try: - str_chars_offset = (offsetof(STR, 'chars') + - itemoffsetof(STR.chars, 0)) + str_chars_offset = (offsetof(STRTYPE, 'chars') + \ + itemoffsetof(STRTYPE.chars, 0)) if gc_buf: src = cast_ptr_to_adr(gc_buf) + str_chars_offset else: - src = cast_ptr_to_adr(raw_buf) + itemoffsetof(CCHARP.TO, 0) + src = cast_ptr_to_adr(raw_buf) + itemoffsetof(TYPEP.TO, 0) dest = cast_ptr_to_adr(new_buf) + str_chars_offset ## FIXME: This is bad, because dest could potentially move ## if there are threads involved. raw_memcopy(src, dest, - llmemory.sizeof(lltype.Char) * needed_size) - return hlstr(new_buf) + llmemory.sizeof(ll_char_type) * needed_size) + return hlstrtype(new_buf) finally: keepalive_until_here(new_buf) @@ -614,15 +639,33 @@ def charp2strn(cp, maxlen): l = [] i = 0 - while i < maxlen and cp[i] != '\x00': + while i < maxlen and cp[i] != lastchar: l.append(cp[i]) i += 1 - return "".join(l) + return emptystr.join(l) # char* and size -> str (which can contain null bytes) def charpsize2str(cp, size): l = [cp[i] for i in range(size)] - return "".join(l) + return emptystr.join(l) + + return (str2charp, free_charp, charp2str, + get_nonmovingbuffer, free_nonmovingbuffer, + alloc_buffer, str_from_buffer, keep_buffer_alive_until_here, + charp2strn, charpsize2str, + ) + +(str2charp, free_charp, charp2str, + get_nonmovingbuffer, free_nonmovingbuffer, + alloc_buffer, str_from_buffer, keep_buffer_alive_until_here, + charp2strn, charpsize2str, + ) = make_string_mappings(str) + +(unicode2wcharp, free_wcharp, wcharp2unicode, + get_nonmoving_unicodebuffer, free_nonmoving_unicodebuffer, + alloc_unicodebuffer, unicode_from_buffer, keep_unicodebuffer_alive_until_here, + wcharp2unicoden, wcharpsize2unicode, + ) = make_string_mappings(unicode) # char** CCHARPP = lltype.Ptr(lltype.Array(CCHARP, hints={'nolength': True})) Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Sun Feb 15 00:05:21 2009 @@ -70,6 +70,19 @@ xf = self.compile(f, [], backendopt=False) assert xf() == 3 + def test_unicode(self): + eci = ExternalCompilationInfo(includes=['string.h']) + z = llexternal('wcslen', [CWCHARP], Signed, compilation_info=eci) + + def f(): + s = unicode2wcharp(u"xxx\xe9") + res = z(s) + free_wcharp(s) + return res + + xf = self.compile(f, [], backendopt=False) + assert xf() == 4 + def test_string_reverse(self): c_source = py.code.Source(""" #include @@ -453,6 +466,20 @@ fn = self.compile(f, [], gcpolicy='ref') assert fn() == d[:-1] + def test_nonmoving_unicode(self): + d = u'non-moving data' + def f(): + raw_buf, gc_buf = alloc_unicodebuffer(len(d)) + try: + for i in range(len(d)): + raw_buf[i] = d[i] + u = unicode_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) + return len(u) + finally: + keep_unicodebuffer_alive_until_here(raw_buf, gc_buf) + assert f() == len(d) - 1 + fn = self.compile(f, [], gcpolicy='ref') + assert fn() == len(d) - 1 def test_nonmovingbuffer(self): d = 'some cool data that should not move' @@ -654,7 +681,7 @@ cache = { lltype.Signed: ctypes.c_long, lltype.Unsigned: ctypes.c_ulong, - lltype.UniChar: ctypes.c_uint, + lltype.UniChar: ctypes.c_wchar, lltype.Char: ctypes.c_ubyte, DOUBLE: ctypes.c_double, SIGNEDCHAR: ctypes.c_byte, From getxsick at codespeak.net Sun Feb 15 00:20:41 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 00:20:41 +0100 (CET) Subject: [pypy-svn] r61899 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090214232041.58DC51684E9@codespeak.net> Author: getxsick Date: Sun Feb 15 00:20:40 2009 New Revision: 61899 Modified: pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) implementation of gettext(), dgettext(), dcgettext() and textdomain(). All tests passed but more tests would be nice. Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Sun Feb 15 00:20:40 2009 @@ -5,12 +5,15 @@ interpleveldefs = { #'lconv': 'interp_locale.lconv', - 'setlocale': 'interp_locale.setlocale', - 'localeconv': 'interp_locale.localeconv', - 'strcoll': 'interp_locale.strcoll', + 'setlocale': 'interp_locale.setlocale', + 'localeconv': 'interp_locale.localeconv', + 'strcoll': 'interp_locale.strcoll', #'strxfrm': 'interp_locale.strxfrm', #'getdefaultlocale': 'interp_locale.getdefaultlocale', - #'gettext': 'interp_locale.gettext', + 'gettext': 'interp_locale.gettext', + 'dgettext': 'interp_locale.dgettext', + 'dcgettext': 'interp_locale.dcgettext', + 'textdomain': 'interp_locale.textdomain', } appleveldefs = { Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sun Feb 15 00:20:40 2009 @@ -192,3 +192,64 @@ strcoll.unwrap_spec = [ObjSpace, W_Root, W_Root] +_gettext = external('gettext', [rffi.CCHARP], rffi.CCHARP) + +def gettext(space, msg): + """gettext(msg) -> string + Return translation of msg.""" + return space.wrap(rffi.charp2str(_gettext(rffi.str2charp(msg)))) + +gettext.unwrap_spec = [ObjSpace, str] + +_dgettext = external('dgettext', [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP) + +def dgettext(space, w_domain, msg): + """dgettext(domain, msg) -> string + Return translation of msg in domain.""" + if space.is_w(w_domain, space.w_None): + domain = None + result = _dgettext(domain, rffi.str2charp(msg)) + else: + domain = space.str_w(w_domain) + result = _dgettext(rffi.str2charp(domain), rffi.str2charp(msg)) + + return space.wrap(rffi.charp2str(result)) + +dgettext.unwrap_spec = [ObjSpace, W_Root, str] + +_dcgettext = external('dcgettext', [rffi.CCHARP, rffi.CCHARP, rffi.INT], rffi.CCHARP) + +def dcgettext(space, w_domain, msg, category): + """dcgettext(domain, msg, category) -> string + Return translation of msg in domain and category.""" + + if space.is_w(w_domain, space.w_None): + domain = None + result = _dcgettext(domain, rffi.str2charp(msg), + rffi.cast(rffi.INT, category)) + else: + domain = space.str_w(w_domain) + result = _dcgettext(rffi.str2charp(domain), rffi.str2charp(msg), + rffi.cast(rffi.INT, category)) + + return space.wrap(rffi.charp2str(result)) + +dcgettext.unwrap_spec = [ObjSpace, W_Root, str, int] + + +_textdomain = external('textdomain', [rffi.CCHARP], rffi.CCHARP) + +def textdomain(space, w_domain): + """textdomain(domain) -> string + Set the C library's textdomain to domain, returning the new domain.""" + + if space.is_w(w_domain, space.w_None): + domain = None + result = _textdomain(domain) + else: + domain = space.str_w(w_domain) + result = _textdomain(rffi.str2charp(domain)) + + return space.wrap(rffi.charp2str(result)) + +textdomain.unwrap_spec = [ObjSpace, W_Root] Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 00:20:40 2009 @@ -128,3 +128,14 @@ _locale.setlocale(_locale.LC_ALL, "pl_PL") assert locale.str(1.1) == '1,1' + def test_text(self): + # TODO more tests would be nice + import _locale + + for fun in ('gettext', 'dgettext', 'dcgettext', 'textdomain'): + assert hasattr(_locale, fun) + + assert _locale.gettext("1234") == "1234" + assert _locale.dgettext(None, "1234") == "1234" + assert _locale.dcgettext(None, "1234", _locale.LC_MESSAGES) == "1234" + assert _locale.textdomain("1234") == "1234" From getxsick at codespeak.net Sun Feb 15 00:22:43 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 00:22:43 +0100 (CET) Subject: [pypy-svn] r61900 - pypy/trunk/pypy/lib Message-ID: <20090214232243.048FF1684E9@codespeak.net> Author: getxsick Date: Sun Feb 15 00:22:43 2009 New Revision: 61900 Modified: pypy/trunk/pypy/lib/_locale.py Log: typo Modified: pypy/trunk/pypy/lib/_locale.py ============================================================================== --- pypy/trunk/pypy/lib/_locale.py (original) +++ pypy/trunk/pypy/lib/_locale.py Sun Feb 15 00:22:43 2009 @@ -343,7 +343,7 @@ def textdomain(domain): """textdomain(domain) -> string - Set the C library's textdmain to domain, returning the new domain.""" + Set the C library's textdomain to domain, returning the new domain.""" return _textdomain(domain) def bindtextdomain(domain, dir): From afa at codespeak.net Sun Feb 15 00:28:43 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 15 Feb 2009 00:28:43 +0100 (CET) Subject: [pypy-svn] r61901 - in pypy/trunk/pypy: rpython/lltypesystem rpython/lltypesystem/test translator/c/src Message-ID: <20090214232843.844F61684E9@codespeak.net> Author: afa Date: Sun Feb 15 00:28:43 2009 New Revision: 61901 Modified: pypy/trunk/pypy/rpython/lltypesystem/rstr.py pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py pypy/trunk/pypy/translator/c/src/rtyper.h pypy/trunk/pypy/translator/c/src/support.h Log: Allow test functions to return runicode strings. Modified: pypy/trunk/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/rstr.py Sun Feb 15 00:28:43 2009 @@ -197,11 +197,24 @@ string_repr = llops.rtyper.type_system.rstr.string_repr v = llops.convertvar(v, r_from, string_repr) cchars = inputconst(Void, "chars") - # xxx put in table - return llops.gencapicall('PyString_FromRPyString', - [v], - resulttype=pyobj_repr, - _callable= lambda v: pyobjectptr(''.join(v.chars))) + # xxx put in table + return llops.gencapicall( + 'PyString_FromRPyString', + [v], + resulttype=pyobj_repr, + _callable=lambda v: pyobjectptr(''.join(v.chars))) + +class __extend__(pairtype(AbstractUnicodeRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + unicode_repr = llops.rtyper.type_system.rstr.unicode_repr + v = llops.convertvar(v, r_from, unicode_repr) + cchars = inputconst(Void, "chars") + # xxx put in table + return llops.gencapicall( + 'PyUnicode_FromRPyUnicode', + [v], + resulttype=pyobj_repr, + _callable=lambda v: pyobjectptr(u''.join(v.chars))) # ____________________________________________________________ # Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Sun Feb 15 00:28:43 2009 @@ -185,7 +185,7 @@ fn = self.compile(f, [], backendopt=False) assert fn() == 8 - def test_externvar(self): + def _test_externvar(self): import os def f(): @@ -473,13 +473,12 @@ try: for i in range(len(d)): raw_buf[i] = d[i] - u = unicode_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) - return len(u) + return unicode_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) finally: keep_unicodebuffer_alive_until_here(raw_buf, gc_buf) - assert f() == len(d) - 1 + assert f() == d[:-1] fn = self.compile(f, [], gcpolicy='ref') - assert fn() == len(d) - 1 + assert fn() == d[:-1] def test_nonmovingbuffer(self): d = 'some cool data that should not move' Modified: pypy/trunk/pypy/translator/c/src/rtyper.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/rtyper.h (original) +++ pypy/trunk/pypy/translator/c/src/rtyper.h Sun Feb 15 00:28:43 2009 @@ -7,6 +7,8 @@ #define RPyString_Size(rps) ((rps)->rs_chars.length) #define RPyString_AsString(rps) ((rps)->rs_chars.items) +#define RPyUnicode_Size(rpu) ((rpu)->ru_chars.length) +#define RPyUnicode_AsUnicode(rpu) ((rpu)->ru_chars.items) /* prototypes */ Modified: pypy/trunk/pypy/translator/c/src/support.h ============================================================================== --- pypy/trunk/pypy/translator/c/src/support.h (original) +++ pypy/trunk/pypy/translator/c/src/support.h Sun Feb 15 00:28:43 2009 @@ -23,6 +23,9 @@ #define PyString_FromRPyString(rpystr) \ PyString_FromStringAndSize(RPyString_AsString(rpystr), RPyString_Size(rpystr)) +#define PyUnicode_FromRPyUnicode(rpystr) \ + PyUnicode_FromUnicode(RPyUnicode_AsUnicode(rpystr), RPyUnicode_Size(rpystr)) + #define PyString_ToRPyString(s, rpystr) \ memcpy(RPyString_AsString(rpystr), PyString_AS_STRING(s), \ RPyString_Size(rpystr)) From afa at codespeak.net Sun Feb 15 00:32:27 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 15 Feb 2009 00:32:27 +0100 (CET) Subject: [pypy-svn] r61902 - pypy/trunk/pypy/rpython/lltypesystem/test Message-ID: <20090214233227.9E3161684C6@codespeak.net> Author: afa Date: Sun Feb 15 00:32:26 2009 New Revision: 61902 Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Log: Did not mean to skip this test Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/trunk/pypy/rpython/lltypesystem/test/test_rffi.py Sun Feb 15 00:32:26 2009 @@ -185,7 +185,7 @@ fn = self.compile(f, [], backendopt=False) assert fn() == 8 - def _test_externvar(self): + def test_externvar(self): import os def f(): From getxsick at codespeak.net Sun Feb 15 00:47:27 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 00:47:27 +0100 (CET) Subject: [pypy-svn] r61903 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090214234727.C80F9168423@codespeak.net> Author: getxsick Date: Sun Feb 15 00:47:25 2009 New Revision: 61903 Modified: pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) unicode arguments for strcoll() supported Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sun Feb 15 00:47:25 2009 @@ -164,7 +164,7 @@ localeconv.unwrap_spec = [ObjSpace] _strcoll = external('strcoll', [rffi.CCHARP, rffi.CCHARP], rffi.INT) -_wcscoll = external('wcscoll', [rffi.WCHAR_TP, rffi.WCHAR_TP], rffi.INT) +_wcscoll = external('wcscoll', [rffi.CWCHARP, rffi.CWCHARP], rffi.INT) def strcoll(space, w_s1, w_s2): "string,string -> int. Compares two strings according to the locale." @@ -182,13 +182,10 @@ s1, s2 = space.unicode_w(w_s1), space.unicode_w(w_s2) - # XXX rffi.unicode2wcharp needed - raise OperationError(space.w_NotImplementedError, - space.wrap("PyPy specific - not implemented for unicode arguments")) - - #s1_c = rffi.str2charp(s1) - #s2_c = rffi.str2charp(s2) - #return space.wrap(_wcscoll(s1_c, s2_c)) + s1_c = rffi.unicode2wcharp(s1) + s2_c = rffi.unicode2wcharp(s2) + result = _wcscoll(s1_c, s2_c) + return space.wrap(result) strcoll.unwrap_spec = [ObjSpace, W_Root, W_Root] Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 00:47:25 2009 @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from pypy.conftest import gettestobjspace import sys @@ -97,9 +98,9 @@ _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") assert _locale.strcoll("a", "b") < 0 - assert _locale.strcoll('\xc4\x85', "b") < 0 + assert _locale.strcoll("?", "b") < 0 - assert _locale.strcoll('\xc4\x87', "b") > 0 + assert _locale.strcoll("?", "b") > 0 assert _locale.strcoll("c", "b") > 0 assert _locale.strcoll("b", "b") == 0 @@ -108,13 +109,12 @@ raises(TypeError, _locale.strcoll, "b", 1) def test_strcoll_unicode(self): - skip("not implemented, rffi.unicode2wcharp needed") import _locale _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") assert _locale.strcoll(u"b", u"b") == 0 - assert _locale.strcoll(u'\xc4\x85', "b") < 0 - assert _locale.strcoll(u'\xc4\x87', "b") > 0 + assert _locale.strcoll(u"a", u"b") < 0 + assert _locale.strcoll(u"b", u"a") > 0 raises(TypeError, _locale.strcoll, 1, u"b") raises(TypeError, _locale.strcoll, u"b", 1) From getxsick at codespeak.net Sun Feb 15 00:50:57 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 00:50:57 +0100 (CET) Subject: [pypy-svn] r61904 - pypy/trunk/pypy/module/_locale/test Message-ID: <20090214235057.D0F151684D7@codespeak.net> Author: getxsick Date: Sun Feb 15 00:50:55 2009 New Revision: 61904 Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) use UTF-8 for convinence Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 00:50:55 2009 @@ -123,9 +123,9 @@ import _locale import locale - _locale.setlocale(_locale.LC_ALL, "en_US") + _locale.setlocale(_locale.LC_ALL, "en_US.UTF-8") assert locale.str(1.1) == '1.1' - _locale.setlocale(_locale.LC_ALL, "pl_PL") + _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") assert locale.str(1.1) == '1,1' def test_text(self): From getxsick at codespeak.net Sun Feb 15 00:53:52 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 00:53:52 +0100 (CET) Subject: [pypy-svn] r61905 - pypy/trunk/pypy/module/_locale/test Message-ID: <20090214235352.9E68C1684DA@codespeak.net> Author: getxsick Date: Sun Feb 15 00:53:52 2009 New Revision: 61905 Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) remove doubled tests Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 00:53:52 2009 @@ -132,9 +132,6 @@ # TODO more tests would be nice import _locale - for fun in ('gettext', 'dgettext', 'dcgettext', 'textdomain'): - assert hasattr(_locale, fun) - assert _locale.gettext("1234") == "1234" assert _locale.dgettext(None, "1234") == "1234" assert _locale.dcgettext(None, "1234", _locale.LC_MESSAGES) == "1234" From getxsick at codespeak.net Sun Feb 15 00:56:20 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 00:56:20 +0100 (CET) Subject: [pypy-svn] r61906 - pypy/trunk/pypy/module/_locale Message-ID: <20090214235620.13F5B1684D8@codespeak.net> Author: getxsick Date: Sun Feb 15 00:56:19 2009 New Revision: 61906 Modified: pypy/trunk/pypy/module/_locale/__init__.py Log: (jlg, getxsick) lconv is not in API anymore Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Sun Feb 15 00:56:19 2009 @@ -4,7 +4,6 @@ """Support for POSIX locales.""" interpleveldefs = { - #'lconv': 'interp_locale.lconv', 'setlocale': 'interp_locale.setlocale', 'localeconv': 'interp_locale.localeconv', 'strcoll': 'interp_locale.strcoll', From afa at codespeak.net Sun Feb 15 01:16:39 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 15 Feb 2009 01:16:39 +0100 (CET) Subject: [pypy-svn] r61907 - in pypy/trunk/pypy/rlib: . test Message-ID: <20090215001639.A38BC1684DA@codespeak.net> Author: afa Date: Sun Feb 15 01:16:39 2009 New Revision: 61907 Modified: pypy/trunk/pypy/rlib/runicode.py pypy/trunk/pypy/rlib/rwin32.py pypy/trunk/pypy/rlib/test/test_runicode.py Log: Really implement the mbcs codecs I'll implement the is_dbcs_lead_byte() function when someone tells me how to test this on a Western windows machine (code page: cp1252) Modified: pypy/trunk/pypy/rlib/runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/runicode.py (original) +++ pypy/trunk/pypy/rlib/runicode.py Sun Feb 15 01:16:39 2009 @@ -489,16 +489,91 @@ return unicode_encode_utf_16_helper(s, size, errors, errorhandler, "little") +# ____________________________________________________________ +# MBCS codecs for Windows + if sys.platform == 'win32': + from pypy.rpython.lltypesystem import lltype, rffi + from pypy.rlib import rwin32 + CP_ACP = 0 + + MultiByteToWideChar = rffi.llexternal('MultiByteToWideChar', + [rffi.UINT, rwin32.DWORD, + rwin32.LPCSTR, rffi.INT, + rffi.CWCHARP, rffi.INT], + rffi.INT, + calling_conv='win') + + WideCharToMultiByte = rffi.llexternal('WideCharToMultiByte', + [rffi.UINT, rwin32.DWORD, + rffi.CWCHARP, rffi.INT, + rwin32.LPCSTR, rffi.INT, + rwin32.LPCSTR, rffi.VOIDP], + rffi.INT, + calling_conv='win') + + def is_dbcs_lead_byte(c): + # XXX don't know how to test this + return False + def str_decode_mbcs(s, size, errors, final=False, errorhandler=None): - # XXX MultiByteToWideChar should be used instead. - return str_decode_latin_1(s, size, errors="replace", - final=final, errorhandler=errorhandler) + if size == 0: + return u"", 0 + + if errorhandler is None: + errorhandler = raise_unicode_exception_decode + + # Skip trailing lead-byte unless 'final' is set + if not final and is_dbcs_lead_byte(s[size-1]): + size -= 1 + + dataptr = rffi.get_nonmovingbuffer(s) + try: + # first get the size of the result + usize = MultiByteToWideChar(CP_ACP, 0, + dataptr, size, + lltype.nullptr(rffi.CWCHARP.TO), 0) + if usize == 0: + raise rwin32.lastWindowsError() + + raw_buf, gc_buf = rffi.alloc_unicodebuffer(usize) + try: + # do the conversion + if MultiByteToWideChar(CP_ACP, 0, + dataptr, size, raw_buf, usize) == 0: + raise rwin32.lastWindowsError() + + return (rffi.unicode_from_buffer(raw_buf, gc_buf, usize, usize), + size) + finally: + rffi.keep_unicodebuffer_alive_until_here(raw_buf, gc_buf) + finally: + rffi.free_nonmovingbuffer(s, dataptr) def unicode_encode_mbcs(p, size, errors, errorhandler=None): - # XXX This is only roughly correct, even on a Western Windows. - # For example, some greek letters do have a translation (phi -> f) - # WideCharToMultiByte should be used instead. - return unicode_encode_latin_1(p, size, errors="replace", - errorhandler=errorhandler) + dataptr = rffi.get_nonmoving_unicodebuffer(p) + try: + # first get the size of the result + if size > 0: + mbcssize = WideCharToMultiByte(CP_ACP, 0, + dataptr, size, None, 0, + None, None) + if mbcssize == 0: + raise rwin32.lastWindowsError() + else: + mbcssize = 0 + + raw_buf, gc_buf = rffi.alloc_buffer(mbcssize) + try: + # do the conversion + if WideCharToMultiByte(CP_ACP, 0, + dataptr, size, raw_buf, mbcssize, + None, None) == 0: + raise rwin32.lastWindowsError() + + return rffi.str_from_buffer(raw_buf, gc_buf, mbcssize, mbcssize) + finally: + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) + finally: + rffi.free_nonmoving_unicodebuffer(p, dataptr) Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Sun Feb 15 01:16:39 2009 @@ -33,6 +33,7 @@ LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) + LPCSTR = rffi_platform.SimpleType("LPCSTR", rffi.CCHARP) LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T) Modified: pypy/trunk/pypy/rlib/test/test_runicode.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_runicode.py (original) +++ pypy/trunk/pypy/rlib/test/test_runicode.py Sun Feb 15 01:16:39 2009 @@ -181,6 +181,15 @@ def test_latin1_error(self): self.checkencodeerror(u"abc\uffff\uffff\uffffcde", "latin-1", 3, 6) + def test_mbcs(self): + if sys.platform != 'win32': + py.test.skip("mbcs encoding is win32-specific") + self.checkencode(u'encoding test', "mbcs") + self.checkdecode('decoding test', "mbcs") + # XXX test this on a non-western Windows installation + self.checkencode(u"\N{GREEK CAPITAL LETTER PHI}", "mbcs") # a F + self.checkencode(u"\N{GREEK CAPITAL LETTER PSI}", "mbcs") # a ? + class TestTranslation(object): def test_utf8(self): from pypy.rpython.test.test_llinterp import interpret From afa at codespeak.net Sun Feb 15 01:20:30 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 15 Feb 2009 01:20:30 +0100 (CET) Subject: [pypy-svn] r61908 - pypy/trunk/pypy/rlib Message-ID: <20090215002030.BC5AE1684DA@codespeak.net> Author: afa Date: Sun Feb 15 01:20:30 2009 New Revision: 61908 Modified: pypy/trunk/pypy/rlib/rmmap.py pypy/trunk/pypy/rlib/rwin32.py Log: Replace LPCTSTR with LPCSTR: the additional 'T' refers to a type that resolves to wchar_t* instead of char* when "#ifdef UNICODE", and this makes little sense with pypy. Modified: pypy/trunk/pypy/rlib/rmmap.py ============================================================================== --- pypy/trunk/pypy/rlib/rmmap.py (original) +++ pypy/trunk/pypy/rlib/rmmap.py Sun Feb 15 01:20:30 2009 @@ -71,7 +71,7 @@ from pypy.rlib.rwin32 import HANDLE, LPHANDLE from pypy.rlib.rwin32 import DWORD, WORD, DWORD_PTR, LPDWORD - from pypy.rlib.rwin32 import BOOL, LPVOID, LPCVOID, LPCTSTR, SIZE_T + from pypy.rlib.rwin32 import BOOL, LPVOID, LPCVOID, LPCSTR, SIZE_T from pypy.rlib.rwin32 import INT, LONG, PLONG # export the constants inside and outside. see __init__.py @@ -165,8 +165,8 @@ GetFileSize = winexternal('GetFileSize', [HANDLE, LPDWORD], DWORD) GetCurrentProcess = winexternal('GetCurrentProcess', [], HANDLE) DuplicateHandle = winexternal('DuplicateHandle', [HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, BOOL, DWORD], BOOL) - CreateFileMapping = winexternal('CreateFileMappingA', [HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCTSTR], HANDLE) - MapViewOfFile = winexternal('MapViewOfFile', [HANDLE, DWORD, DWORD, DWORD, SIZE_T], LPCTSTR)##!!LPVOID) + CreateFileMapping = winexternal('CreateFileMappingA', [HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR], HANDLE) + MapViewOfFile = winexternal('MapViewOfFile', [HANDLE, DWORD, DWORD, DWORD, SIZE_T], LPCSTR)##!!LPVOID) CloseHandle = winexternal('CloseHandle', [HANDLE], BOOL) UnmapViewOfFile = winexternal('UnmapViewOfFile', [LPCVOID], BOOL) FlushViewOfFile = winexternal('FlushViewOfFile', [LPCVOID, SIZE_T], BOOL) @@ -514,7 +514,7 @@ 0, 0, 0) if data: # XXX we should have a real LPVOID which must always be casted - charp = rffi.cast(LPCTSTR, data) + charp = rffi.cast(LPCSTR, data) self.setdata(charp, newsize) return else: @@ -725,7 +725,7 @@ 0, 0, 0) if res: # XXX we should have a real LPVOID which must always be casted - charp = rffi.cast(LPCTSTR, res) + charp = rffi.cast(LPCSTR, res) m.setdata(charp, map_size) return m else: Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Sun Feb 15 01:20:30 2009 @@ -32,7 +32,6 @@ PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP) LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) - LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) LPCSTR = rffi_platform.SimpleType("LPCSTR", rffi.CCHARP) LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T) From getxsick at codespeak.net Sun Feb 15 01:48:46 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 01:48:46 +0100 (CET) Subject: [pypy-svn] r61909 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090215004846.D6AE916849E@codespeak.net> Author: getxsick Date: Sun Feb 15 01:48:43 2009 New Revision: 61909 Modified: pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) strxfrm() implementation. some cleanups. Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Sun Feb 15 01:48:43 2009 @@ -7,7 +7,7 @@ 'setlocale': 'interp_locale.setlocale', 'localeconv': 'interp_locale.localeconv', 'strcoll': 'interp_locale.strcoll', - #'strxfrm': 'interp_locale.strxfrm', + 'strxfrm': 'interp_locale.strxfrm', #'getdefaultlocale': 'interp_locale.getdefaultlocale', 'gettext': 'interp_locale.gettext', 'dgettext': 'interp_locale.dgettext', Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sun Feb 15 01:48:43 2009 @@ -189,6 +189,27 @@ strcoll.unwrap_spec = [ObjSpace, W_Root, W_Root] +_strxfrm = external('strxfrm', [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T], + rffi.SIZE_T) + +def strxfrm(space, s): + "string -> string. Returns a string that behaves for cmp locale-aware." + n1 = len(s) + 1 + try: + buf = lltype.malloc(rffi.CCHARP.TO, n1, flavor="raw", zero=True) + n2 = _strxfrm(buf, rffi.str2charp(s), n1) + 1 + if n2 > n1: + # more space needed + lltype.free(buf, flavor="raw") + buf = lltype.malloc(rffi.CCHARP.TO, n2, flavor="raw", zero=True) + _strxfrm(buf, rffi.str2charp(s), n2) + val = rffi.charp2str(buf) + finally: + lltype.free(buf, flavor="raw") + return space.wrap(val) + +strxfrm.unwrap_spec = [ObjSpace, str] + _gettext = external('gettext', [rffi.CCHARP], rffi.CCHARP) def gettext(space, msg): @@ -214,7 +235,8 @@ dgettext.unwrap_spec = [ObjSpace, W_Root, str] -_dcgettext = external('dcgettext', [rffi.CCHARP, rffi.CCHARP, rffi.INT], rffi.CCHARP) +_dcgettext = external('dcgettext', [rffi.CCHARP, rffi.CCHARP, rffi.INT], + rffi.CCHARP) def dcgettext(space, w_domain, msg, category): """dcgettext(domain, msg, category) -> string Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 01:48:43 2009 @@ -7,10 +7,6 @@ def setup_class(cls): cls.space = gettestobjspace(usemodules=['_locale']) - #cls.w_locale = cls.space.appexec([], """(): - # import locale - # return locale""") - def test_import(self): import _locale assert _locale @@ -119,6 +115,17 @@ raises(TypeError, _locale.strcoll, 1, u"b") raises(TypeError, _locale.strcoll, u"b", 1) + def test_strxfrm(self): + # TODO more tests would be nice + import _locale + + a = "1234" + b = _locale.strxfrm(a) + assert a is not b + assert a == b + + raises(TypeError, _locale.strxfrm, 1) + def test_str_float(self): import _locale import locale From getxsick at codespeak.net Sun Feb 15 02:55:42 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 02:55:42 +0100 (CET) Subject: [pypy-svn] r61910 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090215015542.279401684DE@codespeak.net> Author: getxsick Date: Sun Feb 15 02:55:38 2009 New Revision: 61910 Modified: pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) nl_langinfo() implementation Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Sun Feb 15 02:55:38 2009 @@ -7,12 +7,13 @@ 'setlocale': 'interp_locale.setlocale', 'localeconv': 'interp_locale.localeconv', 'strcoll': 'interp_locale.strcoll', - 'strxfrm': 'interp_locale.strxfrm', + 'strxfrm': 'interp_locale.strxfrm', #'getdefaultlocale': 'interp_locale.getdefaultlocale', 'gettext': 'interp_locale.gettext', 'dgettext': 'interp_locale.dgettext', 'dcgettext': 'interp_locale.dcgettext', 'textdomain': 'interp_locale.textdomain', + 'nl_langinfo': 'interp_locale.nl_langinfo', } appleveldefs = { Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sun Feb 15 02:55:38 2009 @@ -8,7 +8,7 @@ class CConfig: _compilation_info_ = ExternalCompilationInfo( - includes = ['locale.h'] + includes = ['locale.h', 'langinfo.h'] ) lconv = platform.Struct("struct lconv", [ # Numeric (non-monetary) information. @@ -76,6 +76,19 @@ for name in constant_names: setattr(CConfig, name, platform.DefinedConstantInteger(name)) + +langinfo_names = ('CODESET D_T_FMT D_FMT T_FMT RADIXCHAR THOUSEP ' + 'YESEXPR NOEXPR CRNCYSTR AM_STR PM_STR').split(" ") +for i in range(1, 8): + langinfo_names.append("DAY_%d" % i) + langinfo_names.append("ABDAY_%d" % i) +for i in range(1, 13): + langinfo_names.append("MON_%d" % i) + langinfo_names.append("ABMON_%d" % i) + +for name in langinfo_names: + setattr(CConfig, name, platform.DefinedConstantInteger(name)) + class cConfig(object): pass @@ -88,6 +101,11 @@ if value is not None: constants[name] = value +for name in langinfo_names: + value = getattr(cConfig, name) + if value is not None: + constants[name] = value + locals().update(constants) def external(name, args, result): @@ -272,3 +290,17 @@ return space.wrap(rffi.charp2str(result)) textdomain.unwrap_spec = [ObjSpace, W_Root] + +nl_item = rffi.INT +_nl_langinfo = external('nl_langinfo', [nl_item], rffi.CCHARP) + +def nl_langinfo(space, key): + """nl_langinfo(key) -> string + Return the value for the locale information associated with key.""" + + if key in constants.values(): + result = _nl_langinfo(rffi.cast(nl_item, key)) + return space.wrap(rffi.charp2str(result)) + raise OperationError(space.w_ValueError, "unsupported langinfo constant") + +nl_langinfo.unwrap_spec = [ObjSpace, int] Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 02:55:38 2009 @@ -143,3 +143,71 @@ assert _locale.dgettext(None, "1234") == "1234" assert _locale.dcgettext(None, "1234", _locale.LC_MESSAGES) == "1234" assert _locale.textdomain("1234") == "1234" + + def test_nl_langinfo(self): + import _locale + + langinfo_consts = [ + 'ABDAY_1', + 'ABDAY_2', + 'ABDAY_3', + 'ABDAY_4', + 'ABDAY_5', + 'ABDAY_6', + 'ABDAY_7', + 'ABMON_1', + 'ABMON_10', + 'ABMON_11', + 'ABMON_12', + 'ABMON_2', + 'ABMON_3', + 'ABMON_4', + 'ABMON_5', + 'ABMON_6', + 'ABMON_7', + 'ABMON_8', + 'ABMON_9', + 'CODESET', + 'CRNCYSTR', + 'DAY_1', + 'DAY_2', + 'DAY_3', + 'DAY_4', + 'DAY_5', + 'DAY_6', + 'DAY_7', + 'D_FMT', + 'D_T_FMT', + 'MON_1', + 'MON_10', + 'MON_11', + 'MON_12', + 'MON_2', + 'MON_3', + 'MON_4', + 'MON_5', + 'MON_6', + 'MON_7', + 'MON_8', + 'MON_9', + 'NOEXPR', + 'RADIXCHAR', + 'THOUSEP', + 'T_FMT', + 'YESEXPR', + 'AM_STR', + 'PM_STR', + ] + for constant in langinfo_consts: + assert hasattr(_locale, constant) + + _locale.setlocale(_locale.LC_ALL, "C") + assert _locale.nl_langinfo(_locale.ABDAY_1) == "Sun" + assert _locale.nl_langinfo(_locale.ABMON_1) == "Jan" + assert _locale.nl_langinfo(_locale.T_FMT) == "%H:%M:%S" + assert _locale.nl_langinfo(_locale.YESEXPR) == '^[yY]' + assert _locale.nl_langinfo(_locale.NOEXPR) == "^[nN]" + assert _locale.nl_langinfo(_locale.THOUSEP) == '' + + raises(ValueError, _locale.nl_langinfo, 12345) + raises(TypeError, _locale.nl_langinfo, None) From jlg at codespeak.net Sun Feb 15 03:23:25 2009 From: jlg at codespeak.net (jlg at codespeak.net) Date: Sun, 15 Feb 2009 03:23:25 +0100 (CET) Subject: [pypy-svn] r61911 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090215022325.AE9361684D4@codespeak.net> Author: jlg Date: Sun Feb 15 03:23:25 2009 New Revision: 61911 Modified: pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (getxsick, jlg) strxfrm() better test coverage + fixes Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sun Feb 15 03:23:25 2009 @@ -213,17 +213,18 @@ def strxfrm(space, s): "string -> string. Returns a string that behaves for cmp locale-aware." n1 = len(s) + 1 - try: - buf = lltype.malloc(rffi.CCHARP.TO, n1, flavor="raw", zero=True) - n2 = _strxfrm(buf, rffi.str2charp(s), n1) + 1 - if n2 > n1: - # more space needed - lltype.free(buf, flavor="raw") - buf = lltype.malloc(rffi.CCHARP.TO, n2, flavor="raw", zero=True) - _strxfrm(buf, rffi.str2charp(s), n2) - val = rffi.charp2str(buf) - finally: + + buf = lltype.malloc(rffi.CCHARP.TO, n1, flavor="raw", zero=True) + n2 = _strxfrm(buf, rffi.str2charp(s), n1) + 1 + if n2 > n1: + # more space needed lltype.free(buf, flavor="raw") + buf = lltype.malloc(rffi.CCHARP.TO, int(n2), flavor="raw", zero=True) + _strxfrm(buf, rffi.str2charp(s), n2) + + val = rffi.charp2str(buf) + lltype.free(buf, flavor="raw") + return space.wrap(val) strxfrm.unwrap_spec = [ObjSpace, str] Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 03:23:25 2009 @@ -57,6 +57,7 @@ assert string.uppercase == ucase _locale.setlocale(_locale.LC_ALL, "en_US") + assert string.lowercase != lcase assert string.uppercase != ucase @@ -119,6 +120,7 @@ # TODO more tests would be nice import _locale + _locale.setlocale(_locale.LC_ALL, "C") a = "1234" b = _locale.strxfrm(a) assert a is not b @@ -126,6 +128,11 @@ raises(TypeError, _locale.strxfrm, 1) + _locale.setlocale(_locale.LC_ALL, "pl_PL.UTF-8") + a = "1234" + b = _locale.strxfrm(a) + assert a is not b + def test_str_float(self): import _locale import locale From getxsick at codespeak.net Sun Feb 15 03:41:35 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 03:41:35 +0100 (CET) Subject: [pypy-svn] r61912 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090215024135.5658B1684CD@codespeak.net> Author: getxsick Date: Sun Feb 15 03:41:33 2009 New Revision: 61912 Modified: pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) bindtextdomain() implementation. more tests would be nice...for sure Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Sun Feb 15 03:41:33 2009 @@ -14,6 +14,7 @@ 'dcgettext': 'interp_locale.dcgettext', 'textdomain': 'interp_locale.textdomain', 'nl_langinfo': 'interp_locale.nl_langinfo', + 'bindtextdomain': 'interp_locale.bindtextdomain', } appleveldefs = { Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sun Feb 15 03:41:33 2009 @@ -1,5 +1,6 @@ from pypy.rpython.tool import rffi_platform as platform from pypy.rpython.lltypesystem import rffi, lltype +from pypy.rlib import rposix from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import ObjSpace, W_Root @@ -305,3 +306,24 @@ raise OperationError(space.w_ValueError, "unsupported langinfo constant") nl_langinfo.unwrap_spec = [ObjSpace, int] + +_bindtextdomain = external('bindtextdomain', [rffi.CCHARP, rffi.CCHARP], + rffi.CCHARP) + +def bindtextdomain(space, domain, w_dir): + """bindtextdomain(domain, dir) -> string + Bind the C library's domain to dir.""" + + if space.is_w(w_dir, space.w_None): + dir = None + dirname = _bindtextdomain(rffi.str2charp(domain), dir) + else: + dir = space.str_w(w_dir) + dirname = _bindtextdomain(rffi.str2charp(domain), rffi.str2charp(dir)) + + if not dirname: + errno = rposix.get_errno() + raise OperationError(space.w_OSError, errno) + return space.wrap(rffi.charp2str(dirname)) + +bindtextdomain.unwrap_spec = [ObjSpace, str, W_Root] Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 03:41:33 2009 @@ -218,3 +218,10 @@ raises(ValueError, _locale.nl_langinfo, 12345) raises(TypeError, _locale.nl_langinfo, None) + + def test_bindtextdomain(self): + # TODO more tests would be nice + import _locale + + raises(OSError, _locale.bindtextdomain, '', '') + raises(OSError, _locale.bindtextdomain, '', '1') From jlg at codespeak.net Sun Feb 15 03:43:45 2009 From: jlg at codespeak.net (jlg at codespeak.net) Date: Sun, 15 Feb 2009 03:43:45 +0100 (CET) Subject: [pypy-svn] r61913 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090215024345.04B741684CD@codespeak.net> Author: jlg Date: Sun Feb 15 03:43:45 2009 New Revision: 61913 Modified: pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: CHAR_MAX constant added Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sun Feb 15 03:43:45 2009 @@ -9,7 +9,7 @@ class CConfig: _compilation_info_ = ExternalCompilationInfo( - includes = ['locale.h', 'langinfo.h'] + includes = ['locale.h', 'langinfo.h', 'limits.h'] ) lconv = platform.Struct("struct lconv", [ # Numeric (non-monetary) information. @@ -72,6 +72,8 @@ 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION', + # from limits.h + 'CHAR_MAX', ) for name in constant_names: Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 03:43:45 2009 @@ -29,6 +29,7 @@ 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION', + 'CHAR_MAX', ) import _locale From getxsick at codespeak.net Sun Feb 15 04:32:17 2009 From: getxsick at codespeak.net (getxsick at codespeak.net) Date: Sun, 15 Feb 2009 04:32:17 +0100 (CET) Subject: [pypy-svn] r61914 - in pypy/trunk/pypy/module/_locale: . test Message-ID: <20090215033217.A278C1684CF@codespeak.net> Author: getxsick Date: Sun Feb 15 04:32:15 2009 New Revision: 61914 Modified: pypy/trunk/pypy/module/_locale/__init__.py pypy/trunk/pypy/module/_locale/interp_locale.py pypy/trunk/pypy/module/_locale/test/test_locale.py Log: (jlg, getxsick) bind_textdomain_codeset() implementation it should be defined only for some platforms (but now for every) Modified: pypy/trunk/pypy/module/_locale/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_locale/__init__.py (original) +++ pypy/trunk/pypy/module/_locale/__init__.py Sun Feb 15 04:32:15 2009 @@ -4,17 +4,18 @@ """Support for POSIX locales.""" interpleveldefs = { - 'setlocale': 'interp_locale.setlocale', - 'localeconv': 'interp_locale.localeconv', - 'strcoll': 'interp_locale.strcoll', - 'strxfrm': 'interp_locale.strxfrm', - #'getdefaultlocale': 'interp_locale.getdefaultlocale', - 'gettext': 'interp_locale.gettext', - 'dgettext': 'interp_locale.dgettext', - 'dcgettext': 'interp_locale.dcgettext', - 'textdomain': 'interp_locale.textdomain', - 'nl_langinfo': 'interp_locale.nl_langinfo', - 'bindtextdomain': 'interp_locale.bindtextdomain', + 'setlocale': 'interp_locale.setlocale', + 'localeconv': 'interp_locale.localeconv', + 'strcoll': 'interp_locale.strcoll', + 'strxfrm': 'interp_locale.strxfrm', + #'getdefaultlocale': 'interp_locale.getdefaultlocale', + 'gettext': 'interp_locale.gettext', + 'dgettext': 'interp_locale.dgettext', + 'dcgettext': 'interp_locale.dcgettext', + 'textdomain': 'interp_locale.textdomain', + 'nl_langinfo': 'interp_locale.nl_langinfo', + 'bindtextdomain': 'interp_locale.bindtextdomain', + 'bind_textdomain_codeset': 'interp_locale.bind_textdomain_codeset', } appleveldefs = { Modified: pypy/trunk/pypy/module/_locale/interp_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/interp_locale.py (original) +++ pypy/trunk/pypy/module/_locale/interp_locale.py Sun Feb 15 04:32:15 2009 @@ -329,3 +329,26 @@ return space.wrap(rffi.charp2str(dirname)) bindtextdomain.unwrap_spec = [ObjSpace, str, W_Root] + +_bind_textdomain_codeset = external('bind_textdomain_codeset', + [rffi.CCHARP, rffi.CCHARP], rffi.CCHARP) + +# TODO: platform dependent +def bind_textdomain_codeset(space, domain, w_codeset): + """bind_textdomain_codeset(domain, codeset) -> string + Bind the C library's domain to codeset.""" + + if space.is_w(w_codeset, space.w_None): + codeset = None + result = _bind_textdomain_codeset(rffi.str2charp(domain), codeset) + else: + codeset = space.str_w(w_codeset) + result = _bind_textdomain_codeset(rffi.str2charp(domain), + rffi.str2charp(codeset)) + + if not result: + return space.w_None + else: + return space.wrap(rffi.charp2str(result)) + +bind_textdomain_codeset.unwrap_spec = [ObjSpace, str, W_Root] Modified: pypy/trunk/pypy/module/_locale/test/test_locale.py ============================================================================== --- pypy/trunk/pypy/module/_locale/test/test_locale.py (original) +++ pypy/trunk/pypy/module/_locale/test/test_locale.py Sun Feb 15 04:32:15 2009 @@ -226,3 +226,12 @@ raises(OSError, _locale.bindtextdomain, '', '') raises(OSError, _locale.bindtextdomain, '', '1') + + def test_bind_textdomain_codeset(self): + import _locale + + assert _locale.bind_textdomain_codeset('/', None) is None + assert _locale.bind_textdomain_codeset('/', 'UTF-8') == 'UTF-8' + assert _locale.bind_textdomain_codeset('/', None) == 'UTF-8' + + assert _locale.bind_textdomain_codeset('', '') is None From fijal at codespeak.net Sun Feb 15 10:05:02 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 10:05:02 +0100 (CET) Subject: [pypy-svn] r61915 - pypy/trunk/pypy/doc/config Message-ID: <20090215090502.1A9E61684C5@codespeak.net> Author: fijal Date: Sun Feb 15 10:05:00 2009 New Revision: 61915 Removed: pypy/trunk/pypy/doc/config/objspace.pyversion.txt Log: this option is gone by now From fijal at codespeak.net Sun Feb 15 10:47:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 10:47:08 +0100 (CET) Subject: [pypy-svn] r61916 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090215094708.E0A181684C5@codespeak.net> Author: fijal Date: Sun Feb 15 10:47:05 2009 New Revision: 61916 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Log: Add a test for tl Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Sun Feb 15 10:47:05 2009 @@ -43,7 +43,7 @@ res = self.meta_interp(main, [1, 10]) assert res == 100 - def test_tl_base(self): + def setup_class(cls): from pypy.jit.tl.tl import interp_without_call from pypy.jit.tl.tlopcode import compile @@ -70,20 +70,41 @@ POP RETURN ''') + + code2 = compile(''' + PUSHARG + start: + PUSH 1 + SUB + PICK 0 + PUSH 1 + LE + BR_COND exit + PUSH 1 + BR_COND start + exit: + RETURN + ''') - codes = ["", code] + codes = [code, code2] def main(n, inputarg): code = codes[n] return interp_without_call(code, inputarg=inputarg) + cls.main = main - res = self.meta_interp(main, [1, 6]) - # eventually this loop should become really virtual + def test_tl_base(self): + res = self.meta_interp(self.main.im_func, [0, 6]) self.check_loops({'merge_point':1, 'int_mul':1, 'jump':1, 'int_sub':1, 'int_is_true':1, 'int_le':1, 'guard_false':1}) assert res == 5040 + def test_tl_2(self): + res = self.meta_interp(self.main.im_func, [1, 10]) + assert res == self.main(1, 10) + self.check_loop({'merge_point':1, 'int_sub':1, 'int_le':1, + 'int_is_true':1, 'guard_false':1, 'jump':1}) class TestOOtype(ToyLanguageTests, OOJitMixin): pass From fijal at codespeak.net Sun Feb 15 11:54:03 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 11:54:03 +0100 (CET) Subject: [pypy-svn] r61917 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090215105403.2224B168423@codespeak.net> Author: fijal Date: Sun Feb 15 11:54:01 2009 New Revision: 61917 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Log: Add extra checks + fix tests Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Sun Feb 15 11:54:01 2009 @@ -68,10 +68,10 @@ _prev = Box._extended_display try: Box._extended_display = False - #if len(self.graphs) > 1: - # graphs = self.graphs[1:] - #else: - graphs = self.graphs + if len(self.graphs) > 1: + graphs = self.graphs[1:] + else: + graphs = self.graphs for i, graph in enumerate(graphs): self.gengraph(graph, i) finally: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 11:54:01 2009 @@ -36,17 +36,20 @@ self.list_allocations = [] self.setitems = [] - def deal_with_box(self, box, nodes, liveboxes, memo): + def deal_with_box(self, box, nodes, liveboxes, memo, ready): if isinstance(box, Const): virtual = False virtualized = False else: + prevbox = box instnode = nodes[box] box = instnode.source if box in memo: return memo[box] virtual = instnode.virtual virtualized = instnode.virtualized + if not virtual: + assert box in ready if virtual: if isinstance(instnode.cls.source, ListDescr): ld = instnode.cls.source @@ -65,7 +68,8 @@ res = alloc_offset memo[box] = res for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo) + num = self.deal_with_box(node.source, nodes, liveboxes, memo, + ready) if isinstance(instnode.cls.source, ListDescr): ld = instnode.cls.source x = (alloc_offset + 1) << 16 @@ -77,7 +81,8 @@ memo[box] = res liveboxes.append(box) for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo) + num = self.deal_with_box(node.source, nodes, liveboxes, memo, + ready) self.setfields.append((res, ofs, num)) else: res = ~len(liveboxes) @@ -429,7 +434,8 @@ op = op.clone() for box in old_boxes: indices.append(storage.deal_with_box(box, self.nodes, - liveboxes, memo)) + liveboxes, memo, + self.ready_results)) rev_boxes = {} for i in range(len(liveboxes)): box = liveboxes[i] @@ -467,6 +473,7 @@ instnode = self.nodes[box] assert not instnode.virtual box = instnode.source + assert isinstance(box, Const) or box in self.ready_results newboxes.append(box) return newboxes @@ -496,6 +503,7 @@ # we never perform this operation here, note def optimize_loop(self): + self.ready_results = {} newoperations = [] exception_might_have_happened = False mp = self.loop.operations[0] @@ -511,12 +519,19 @@ assert not self.nodes[box].virtual for op in self.loop.operations: + if newoperations and newoperations[-1].results: + self.ready_results[newoperations[-1].results[0]] = None opname = op.opname if opname == 'merge_point': args = self.expanded_version_of(op.args, None) op = MergePoint('merge_point', args, []) newoperations.append(op) + for arg in op.args: + self.ready_results[arg] = None continue + elif opname == 'catch': + for arg in op.args: + self.ready_results[arg] = None elif opname == 'jump': args = self.expanded_version_of(op.args, newoperations) self.cleanup_field_caches(newoperations) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Sun Feb 15 11:54:01 2009 @@ -102,8 +102,8 @@ def test_tl_2(self): res = self.meta_interp(self.main.im_func, [1, 10]) - assert res == self.main(1, 10) - self.check_loop({'merge_point':1, 'int_sub':1, 'int_le':1, + assert res == self.main.im_func(1, 10) + self.check_loops({'merge_point':1, 'int_sub':1, 'int_le':1, 'int_is_true':1, 'guard_false':1, 'jump':1}) class TestOOtype(ToyLanguageTests, OOJitMixin): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Sun Feb 15 11:54:01 2009 @@ -168,6 +168,11 @@ res = self.meta_interp(f, [20]) assert res == 9 + #def test_virtual_and_only_setfield(self): + # myjitdriver = JitDriver(greens = [], reds = ['n', 'i']) + + # def f(n): + ##class TestOOtype(VirtualTests, OOJitMixin): ## _new = staticmethod(ootype.new) From fijal at codespeak.net Sun Feb 15 12:22:09 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 12:22:09 +0100 (CET) Subject: [pypy-svn] r61923 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090215112209.E15081684BF@codespeak.net> Author: fijal Date: Sun Feb 15 12:22:09 2009 New Revision: 61923 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Initialize virtual list. A bit suboptimal, but makes test_tlc pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 12:22:09 2009 @@ -151,6 +151,7 @@ d.update(self.origfields) else: d = other.curfields + d = other.curfields lst = d.items() lst.sort() for ofs, node in lst: @@ -296,6 +297,8 @@ instnode = InstanceNode(box, escaped=False) self.nodes[box] = instnode self.first_escaping_op = False + # XXX we don't support lists with variable length + assert isinstance(op.args[1], ConstInt) instnode.known_length = op.args[1].getint() # XXX following guard_builtin will set the # correct class, otherwise it's a mess @@ -603,7 +606,11 @@ assert isinstance(instnode.cls.source, ListDescr) if not instnode.escaped: instnode.virtual = True - assert isinstance(instnode.cls.source, ListDescr) + for i in range(instnode.known_length): + instnode.curfields[i] = InstanceNode(op.args[2], + const=True) + for ofs, item in instnode.origfields.items(): + self.nodes[item.source] = instnode.curfields[ofs] continue elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Sun Feb 15 12:22:09 2009 @@ -44,7 +44,6 @@ assert res == 42 def test_accumulator(self): - py.test.skip("bugs") path = py.path.local(tlc.__file__).dirpath('accumulator.tlc.src') code = path.read() res = self.exec_code(code, 20) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Sun Feb 15 12:22:09 2009 @@ -168,12 +168,6 @@ res = self.meta_interp(f, [20]) assert res == 9 - #def test_virtual_and_only_setfield(self): - # myjitdriver = JitDriver(greens = [], reds = ['n', 'i']) - - # def f(n): - - ##class TestOOtype(VirtualTests, OOJitMixin): ## _new = staticmethod(ootype.new) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sun Feb 15 12:22:09 2009 @@ -60,6 +60,24 @@ # one setitem should be gone by now self.check_loops(newlist=1, setitem=1, getitem=1) + def test_vlist_with_default_read(self): + jitdriver = JitDriver(greens = [], reds = ['n']) + def f(n): + l = [1] * 20 + while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) + l = [0] * 20 + x = l[3] + if n < 3: + return x + n -= 1 + return l[0] + + res = self.meta_interp(f, [10]) + assert res == f(10) + + def test_append_pop(self): py.test.skip("XXX") def f(n): From fijal at codespeak.net Sun Feb 15 12:22:56 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 12:22:56 +0100 (CET) Subject: [pypy-svn] r61924 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090215112256.88BA51684CA@codespeak.net> Author: fijal Date: Sun Feb 15 12:22:55 2009 New Revision: 61924 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: A fix it's a derived constant Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 12:22:55 2009 @@ -606,8 +606,10 @@ assert isinstance(instnode.cls.source, ListDescr) if not instnode.escaped: instnode.virtual = True + valuesource = self.getsource(op.args[2]) + assert isinstance(valuesource, Const) for i in range(instnode.known_length): - instnode.curfields[i] = InstanceNode(op.args[2], + instnode.curfields[i] = InstanceNode(valuesource, const=True) for ofs, item in instnode.origfields.items(): self.nodes[item.source] = instnode.curfields[ofs] From fijal at codespeak.net Sun Feb 15 12:56:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 12:56:38 +0100 (CET) Subject: [pypy-svn] r61925 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090215115638.DD82E1684BD@codespeak.net> Author: fijal Date: Sun Feb 15 12:56:36 2009 New Revision: 61925 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: trivial fix, only supports lists with integers Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 12:56:36 2009 @@ -606,7 +606,11 @@ assert isinstance(instnode.cls.source, ListDescr) if not instnode.escaped: instnode.virtual = True - valuesource = self.getsource(op.args[2]) + if len(op.args) > 2: + valuesource = self.getsource(op.args[2]) + else: + # XXX check for type + valuesource = ConstInt(0) assert isinstance(valuesource, Const) for i in range(instnode.known_length): instnode.curfields[i] = InstanceNode(valuesource, @@ -762,8 +766,9 @@ [setfunc, box, ConstInt(ofs), itembox], 'void', False) if storage.setitems: + #history.execute_and_record('guard_no_exception', [], 'void', False) # XXX this needs to check for exceptions somehow - # create guard_no_excpetion somehow + # create guard_no_excpetion somehow, needs tests pass newboxes = [] for index in storage.indices: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sun Feb 15 12:56:36 2009 @@ -77,7 +77,6 @@ res = self.meta_interp(f, [10]) assert res == f(10) - def test_append_pop(self): py.test.skip("XXX") def f(n): From fijal at codespeak.net Sun Feb 15 12:58:31 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 12:58:31 +0100 (CET) Subject: [pypy-svn] r61926 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090215115831.436CA1684BD@codespeak.net> Author: fijal Date: Sun Feb 15 12:58:30 2009 New Revision: 61926 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: A proper fix Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 12:58:30 2009 @@ -606,11 +606,7 @@ assert isinstance(instnode.cls.source, ListDescr) if not instnode.escaped: instnode.virtual = True - if len(op.args) > 2: - valuesource = self.getsource(op.args[2]) - else: - # XXX check for type - valuesource = ConstInt(0) + valuesource = self.getsource(op.args[2]) assert isinstance(valuesource, Const) for i in range(instnode.known_length): instnode.curfields[i] = InstanceNode(valuesource, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Feb 15 12:58:30 2009 @@ -399,6 +399,11 @@ @arguments("builtin", "varargs") def opimpl_newlist(self, descr, varargs): args = [descr.malloc_func] + varargs + if len(varargs) == 1: + if descr.tp == "int": + args.append(ConstInt(0)) + else: + args.append(ConstPtr(lltype.nullptr(llmemory.GCREF.TO))) op = self.execute_with_exc('newlist', args, 'ptr') @arguments("indirectcallset", "box", "varargs") From fijal at codespeak.net Sun Feb 15 14:32:11 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 14:32:11 +0100 (CET) Subject: [pypy-svn] r61935 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090215133211.5795116847E@codespeak.net> Author: fijal Date: Sun Feb 15 14:32:09 2009 New Revision: 61935 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: A bit of support for virtual lists with length. Right now escaping rules are messy, ie it will all explode if you try to escape Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sun Feb 15 14:32:09 2009 @@ -18,10 +18,14 @@ pass class ListDescr(BuiltinDescr): - def __init__(self, getfunc, setfunc, malloc_func, tp): + def __init__(self, getfunc, setfunc, malloc_func, append_func, + pop_func, len_func, tp): self.setfunc = setfunc self.getfunc = getfunc self.malloc_func = malloc_func + self.append_func = append_func + self.pop_func = pop_func + self.len_func = len_func self.tp = tp def equals(self, other): @@ -145,22 +149,46 @@ try: return self.list_cache[TP.TO] except KeyError: + if isinstance(TP.TO, lltype.GcStruct): + OF = TP.TO.items.TO.OF + else: + OF = TP.TO.OF rtyper = self.rtyper - args = [TP, lltype.Signed, TP.TO.OF] + args = [TP, lltype.Signed, OF] setfunc, _ = support.builtin_func_for_spec(rtyper, 'list.setitem', args, lltype.Void) getfunc, _ = support.builtin_func_for_spec(rtyper, 'list.getitem', - args[:-1], TP.TO.OF) + args[:-1], OF) malloc_func, _ = support.builtin_func_for_spec(rtyper, 'newlist', [lltype.Signed], TP) - if isinstance(TP.TO.OF, lltype.Number): + len_func, _ = support.builtin_func_for_spec(rtyper, 'list.len', + [TP], lltype.Signed) + + if isinstance(TP.TO, lltype.GcStruct): + append_func, _ = support.builtin_func_for_spec(rtyper, + 'list.append', + [TP, OF], lltype.Void) + pop_func, _ = support.builtin_func_for_spec(rtyper, 'list.pop', + [TP], OF) + if isinstance(OF, lltype.Number): tp = "int" else: tp = "ptr" - ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), - history.ConstAddr(setfunc.value, self.cpu), - history.ConstAddr(malloc_func.value, self.cpu), - tp) + if isinstance(TP.TO, lltype.GcStruct): + ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), + history.ConstAddr(setfunc.value, self.cpu), + history.ConstAddr(malloc_func.value, self.cpu), + history.ConstAddr(append_func.value, self.cpu), + history.ConstAddr(pop_func.value, self.cpu), + history.ConstAddr(len_func.value, self.cpu), + tp) + else: + ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), + history.ConstAddr(setfunc.value, self.cpu), + history.ConstAddr(malloc_func.value, self.cpu), + None, None, + history.ConstAddr(len_func.value, self.cpu), + tp) self.list_cache[TP.TO] = ld return ld @@ -560,15 +588,23 @@ self.emit('can_enter_jit') self.emit_varargs(op.args[2:]) - def _eventualy_builtin(self, arg): + def _eventualy_builtin(self, arg, need_length=True): if isinstance(arg.concretetype, lltype.Ptr): # XXX very complex logic for getting all things # that are pointers, but not objects + is_list = False if isinstance(arg.concretetype.TO, lltype.GcArray): + is_list = True + if isinstance(arg.concretetype.TO, lltype.GcStruct): + if arg.concretetype.TO._hints.get('list'): + is_list = True + if is_list: descr = self.codewriter.list_descr_for_tp(arg.concretetype) self.emit('guard_builtin', self.var_position(arg), self.get_position(descr)) - + if need_length: + self.emit('guard_len', self.var_position(arg), + self.get_position(descr)) #def serialize_op_direct_call(self, op): # color = support.guess_call_kind(self.codewriter.hannotator, op) @@ -609,14 +645,19 @@ c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper, oopspec_name, ll_args, op.result.concretetype) - if ((oopspec_name.startswith('list') or oopspec_name == 'newlist') and - not isinstance(TP.TO, lltype.GcStruct)): + if oopspec_name.startswith('list') or oopspec_name == 'newlist': if oopspec_name.startswith('list.getitem'): opname = oopspec_name[len('list.'):] elif oopspec_name.startswith('list.setitem'): opname = oopspec_name[len('list.'):] elif oopspec_name == 'newlist': opname = 'newlist' + elif oopspec_name == 'list.append': + opname = 'append' + elif oopspec_name == 'list.pop': + opname = 'pop' + elif oopspec_name == 'list.len': + opname = 'len' else: raise NotImplementedError("not supported %s" % oopspec_name) self.emit(opname) @@ -625,7 +666,7 @@ self.emit_varargs(args) self.register_var(op.result) if opname == 'newlist': - self._eventualy_builtin(op.result) + self._eventualy_builtin(op.result, False) return if oopspec_name.endswith('_foldable'): opname = 'green_call_%s' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 14:32:09 2009 @@ -56,9 +56,7 @@ assert isinstance(ld, ListDescr) alloc_offset = len(self.list_allocations) malloc_func = ld.malloc_func - if instnode.known_length == -1: - # XXX - instnode.known_length = 42 + assert instnode.known_length != -1 self.list_allocations.append((malloc_func, instnode.known_length)) res = (alloc_offset + 1) << 16 @@ -145,6 +143,9 @@ return FixedListSpecNode(known_class) return FixedClassSpecNode(known_class) if not other.escaped: + if (isinstance(known_class, ListDescr) + and self.known_length != other.known_length): + XXX # XXX think fields = [] if self is other: d = other.curfields @@ -162,7 +163,8 @@ specnode = NotSpecNode() fields.append((ofs, specnode)) if isinstance(known_class, ListDescr): - return VirtualListSpecNode(known_class, fields) + return VirtualListSpecNode(known_class, fields, + other.known_length) return VirtualInstanceSpecNode(known_class, fields) if not other.virtualized and self.expanded_fields: fields = [] @@ -279,10 +281,10 @@ def find_nodes(self): # Steps (1) and (2) self.first_escaping_op = True + # only catch can have consts for box in self.loop.operations[0].args: self.nodes[box] = InstanceNode(box, escaped=False, startbox=True, const=isinstance(box, Const)) - for op in self.loop.operations[1:-1]: opname = op.opname if opname == 'new_with_vtable': @@ -308,6 +310,10 @@ # all builtins have equal classes instnode.cls = InstanceNode(op.args[1]) continue + elif opname == 'guard_len': + instnode = self.nodes[op.args[0]] + instnode.known_length = op.args[1].getint() + continue elif opname == 'setfield_gc': instnode = self.getnode(op.args[0]) fieldbox = op.args[1] @@ -335,6 +341,29 @@ continue else: instnode.escaped = True + elif opname == 'append': + instnode = self.getnode(op.args[1]) + assert isinstance(instnode.cls.source, ListDescr) + assert instnode.known_length != -1 + field = instnode.known_length + instnode.known_length += 1 + self.find_nodes_setfield(instnode, field, + self.getnode(op.args[2])) + continue + elif opname == 'pop': + instnode = self.getnode(op.args[1]) + assert isinstance(instnode.cls.source, ListDescr) + assert instnode.known_length != -1 + instnode.known_length -= 1 + field = instnode.known_length + self.find_nodes_getfield(instnode, field, op.results[0]) + continue + elif opname == 'len': + instnode = self.getnode(op.args[1]) + assert instnode.known_length != -1 + lgtbox = op.results[0].constbox() + self.nodes[op.results[0]] = InstanceNode(lgtbox, const=True) + continue elif opname == 'setitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] @@ -554,6 +583,13 @@ if instnode.cls is None: instnode.cls = InstanceNode(op.args[1]) continue + elif opname == 'guard_len': + # it should be completely gone, because if it escapes + # we don't virtualize it anymore + if not instnode.escaped: + instnode = self.nodes[op.args[0]] + instnode.known_length = op.args[1].getint() + continue elif opname == 'guard_nonvirtualized': instnode = self.nodes[op.args[0]] if instnode.virtualized: @@ -608,12 +644,33 @@ instnode.virtual = True valuesource = self.getsource(op.args[2]) assert isinstance(valuesource, Const) - for i in range(instnode.known_length): + maxlength = max(instnode.curfields.keys() + + instnode.origfields.keys()) + for i in range(maxlength + 1): instnode.curfields[i] = InstanceNode(valuesource, const=True) for ofs, item in instnode.origfields.items(): self.nodes[item.source] = instnode.curfields[ofs] + instnode.known_length = op.args[1].getint() + continue + elif opname == 'append': + instnode = self.nodes[op.args[1]] + valuenode = self.nodes[op.args[2]] + ofs = instnode.known_length + instnode.known_length += 1 + assert ofs != -1 + self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) + continue + elif opname == 'pop': + instnode = self.nodes[op.args[1]] + instnode.known_length -= 1 + ofs = instnode.known_length + if self.optimize_getfield(instnode, ofs, op.results[0]): continue + elif opname == 'len': + instnode = self.nodes[op.args[1]] + assert instnode.known_length + continue elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Feb 15 14:32:09 2009 @@ -404,7 +404,22 @@ args.append(ConstInt(0)) else: args.append(ConstPtr(lltype.nullptr(llmemory.GCREF.TO))) - op = self.execute_with_exc('newlist', args, 'ptr') + self.execute_with_exc('newlist', args, 'ptr') + + @arguments("builtin", "varargs") + def opimpl_append(self, descr, varargs): + args = [descr.append_func] + varargs + self.execute_with_exc('append', args, 'void') + + @arguments("builtin", "varargs") + def opimpl_pop(self, descr, varargs): + args = [descr.pop_func] + varargs + self.execute_with_exc('pop', args, descr.tp) + + @arguments("builtin", "varargs") + def opimpl_len(self, descr, varargs): + args = [descr.len_func] + varargs + self.execute_with_exc('len', args, 'int') @arguments("indirectcallset", "box", "varargs") def opimpl_indirect_call(self, indirectcallset, box, varargs): @@ -446,6 +461,12 @@ def opimpl_guard_builtin(self, pc, box, builtin): self.generate_guard(pc, "guard_builtin", box, [builtin]) + @arguments("orgpc", "box", "builtin") + def opimpl_guard_len(self, pc, box, builtin): + intbox = self.metainterp.cpu.execute_operation( + 'len', [builtin.len_func, box], 'int') + self.generate_guard(pc, "guard_len", box, [intbox]) + @arguments("orgpc", "box", "virtualizabledesc", "int") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): clsbox = self.cls_of_box(box) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Sun Feb 15 14:32:09 2009 @@ -217,6 +217,14 @@ class VirtualListSpecNode(VirtualSpecNode): + def __init__(self, known_class, fields, known_length): + VirtualSpecNode.__init__(self, known_class, fields) + self.known_length = known_length + + def mutate_nodes(self, instnode): + VirtualSpecNode.mutate_nodes(self, instnode) + instnode.known_length = self.known_length + def equals(self, other): if not isinstance(other, VirtualListSpecNode): return False Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sun Feb 15 14:32:09 2009 @@ -9,7 +9,7 @@ def check_all_virtualized(self): self.check_loops(new=0, newlist=0, - getitem=0, setitem=0) + getitem=0, setitem=0, append=0, pop=0, len=0) def test_simple_array(self): jitdriver = JitDriver(greens = [], reds = ['n']) @@ -78,9 +78,11 @@ assert res == f(10) def test_append_pop(self): - py.test.skip("XXX") + jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) lst = [] lst.append(5) lst.append(n) From fijal at codespeak.net Sun Feb 15 14:50:20 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 14:50:20 +0100 (CET) Subject: [pypy-svn] r61936 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090215135020.858801684A7@codespeak.net> Author: fijal Date: Sun Feb 15 14:50:17 2009 New Revision: 61936 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: support for insert (only for virtual lists, otherwise explodes) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sun Feb 15 14:50:17 2009 @@ -83,9 +83,13 @@ 'strlen' : (('ptr',), 'int'), 'strgetitem' : (('ptr', 'int'), 'int'), 'strsetitem' : (('ptr', 'int', 'int'), None), - 'getitem' : (('ptr', 'ptr', 'int'), 'int'), - 'setitem' : (('ptr', 'ptr', 'int', 'int'), None), - 'newlist' : (('ptr', 'varargs'), 'ptr'), + 'getitem' : (('void', 'ptr', 'int'), 'int'), + 'setitem' : (('void', 'ptr', 'int', 'int'), None), + 'newlist' : (('void', 'varargs'), 'ptr'), + 'append' : (('void', 'ptr', 'int'), None), + 'insert' : (('void', 'ptr', 'int', 'int'), None), + 'pop' : (('void', 'ptr',), 'int'), + 'len' : (('void', 'ptr',), 'int'), } # ____________________________________________________________ @@ -158,6 +162,8 @@ tp = "int" if tp == 'int': return str(x) + elif tp == 'void': + return '' elif tp == 'ptr': if not x: return '(* None)' @@ -756,11 +762,18 @@ op_call_ptr = do_call op_call_void = do_call - def op_getitem(self, ll_getitem, lst, item): - return self.do_call(ll_getitem, lst, item) + def op_listop_return(self, ll_func, *args): + return self.do_call(ll_func, *args) - def op_setitem(self, ll_setitem, lst, item, val): - self.do_call(ll_setitem, lst, item, val) + def op_listop(self, ll_func, *args): + self.do_call(ll_func, *args) + + op_getitem = op_listop_return + op_setitem = op_listop + op_append = op_listop + op_insert = op_listop + op_pop = op_listop_return + op_len = op_listop_return def op_newlist(self, ll_newlist, lgt, default_val=None): res = self.do_call(ll_newlist, lgt) @@ -772,8 +785,12 @@ else: default_val = lltype.nullptr(TP.TO) if default_val is not None: - for i in range(len(res)): - res[i] = default_val + if hasattr(res, 'items'): + items = res.items + else: + items = res + for i in range(len(items)): + items[i] = default_val return res def op_cast_int_to_ptr(self, i): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sun Feb 15 14:50:17 2009 @@ -19,11 +19,12 @@ class ListDescr(BuiltinDescr): def __init__(self, getfunc, setfunc, malloc_func, append_func, - pop_func, len_func, tp): + pop_func, insert_func, len_func, tp): self.setfunc = setfunc self.getfunc = getfunc self.malloc_func = malloc_func self.append_func = append_func + self.insert_func = insert_func self.pop_func = pop_func self.len_func = len_func self.tp = tp @@ -170,6 +171,8 @@ [TP, OF], lltype.Void) pop_func, _ = support.builtin_func_for_spec(rtyper, 'list.pop', [TP], OF) + insert_func, _ = support.builtin_func_for_spec(rtyper, + 'list.insert', [TP, lltype.Signed, OF], lltype.Void) if isinstance(OF, lltype.Number): tp = "int" else: @@ -180,13 +183,14 @@ history.ConstAddr(malloc_func.value, self.cpu), history.ConstAddr(append_func.value, self.cpu), history.ConstAddr(pop_func.value, self.cpu), + history.ConstAddr(insert_func.value, self.cpu), history.ConstAddr(len_func.value, self.cpu), tp) else: ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), history.ConstAddr(setfunc.value, self.cpu), history.ConstAddr(malloc_func.value, self.cpu), - None, None, + None, None, None, history.ConstAddr(len_func.value, self.cpu), tp) self.list_cache[TP.TO] = ld @@ -658,6 +662,8 @@ opname = 'pop' elif oopspec_name == 'list.len': opname = 'len' + elif oopspec_name == 'list.insert': + opname = 'insert' else: raise NotImplementedError("not supported %s" % oopspec_name) self.emit(opname) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 14:50:17 2009 @@ -276,7 +276,14 @@ instnode.origfields[field] = fieldnode self.nodes[box] = fieldnode if self.first_escaping_op: - instnode.expanded_fields[field] = None + instnode.expanded_fields[field] = None + + def find_nodes_insert(self, instnode, field, fieldnode): + for ofs, node in instnode.curfields.items(): + if ofs >= field: + instnode.curfields[ofs + 1] = node + instnode.curfields[field] = fieldnode + self.dependency_graph.append((instnode, fieldnode)) def find_nodes(self): # Steps (1) and (2) @@ -350,6 +357,16 @@ self.find_nodes_setfield(instnode, field, self.getnode(op.args[2])) continue + elif opname == 'insert': + instnode = self.getnode(op.args[1]) + assert isinstance(instnode.cls.source, ListDescr) + assert instnode.known_length != -1 + fieldbox = self.getsource(op.args[2]) + assert isinstance(fieldbox, Const) or fieldbox.const + field = fieldbox.getint() + self.find_nodes_insert(instnode, field, + self.getnode(op.args[3])) + continue elif opname == 'pop': instnode = self.getnode(op.args[1]) assert isinstance(instnode.cls.source, ListDescr) @@ -534,6 +551,13 @@ instnode.dirtyfields[ofs] = self.nodes[valuebox] # we never perform this operation here, note + def optimize_insert(self, instnode, field, valuenode, valuebox): + assert instnode.virtual + for ofs, node in instnode.curfields.items(): + if ofs >= field: + instnode.curfields[ofs + 1] = node + instnode.curfields[field] = valuenode + def optimize_loop(self): self.ready_results = {} newoperations = [] @@ -661,6 +685,12 @@ assert ofs != -1 self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) continue + elif opname == 'insert': + instnode = self.nodes[op.args[1]] + ofs = self.getsource(op.args[2]).getint() + valuenode = self.nodes[op.args[3]] + self.optimize_insert(instnode, ofs, valuenode, op.args[3]) + continue elif opname == 'pop': instnode = self.nodes[op.args[1]] instnode.known_length -= 1 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Feb 15 14:50:17 2009 @@ -412,6 +412,11 @@ self.execute_with_exc('append', args, 'void') @arguments("builtin", "varargs") + def opimpl_insert(self, descr, varargs): + args = [descr.insert_func] + varargs + self.execute_with_exc('insert', args, 'void') + + @arguments("builtin", "varargs") def opimpl_pop(self, descr, varargs): args = [descr.pop_func] + varargs self.execute_with_exc('pop', args, descr.tp) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sun Feb 15 14:50:17 2009 @@ -9,7 +9,8 @@ def check_all_virtualized(self): self.check_loops(new=0, newlist=0, - getitem=0, setitem=0, append=0, pop=0, len=0) + getitem=0, setitem=0, append=0, pop=0, len=0, + insert=0) def test_simple_array(self): jitdriver = JitDriver(greens = [], reds = ['n']) @@ -95,15 +96,19 @@ self.check_all_virtualized() def test_insert(self): - py.test.skip("XXX") + jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) lst = [1, 2, 3] lst.insert(0, n) - n = lst[0] - 10 + n = lst[0] - 1 + lst.pop() + # last pop is needed, otherwise it won't work return n - res = self.meta_interp(f, [33], exceptions=False) - assert res == -7 + res = self.meta_interp(f, [33]) + assert res == f(33) self.check_all_virtualized() def test_list_escapes(self): From fijal at codespeak.net Sun Feb 15 15:03:16 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 15:03:16 +0100 (CET) Subject: [pypy-svn] r61937 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090215140316.D964B1684B6@codespeak.net> Author: fijal Date: Sun Feb 15 15:03:16 2009 New Revision: 61937 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Support for list.nonzero. Next step - make tlc use virtualizables in a nice way Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Sun Feb 15 15:03:16 2009 @@ -90,6 +90,7 @@ 'insert' : (('void', 'ptr', 'int', 'int'), None), 'pop' : (('void', 'ptr',), 'int'), 'len' : (('void', 'ptr',), 'int'), + 'listnonzero' : (('void', 'ptr',), 'int'), } # ____________________________________________________________ @@ -774,12 +775,16 @@ op_insert = op_listop op_pop = op_listop_return op_len = op_listop_return + op_listnonzero = op_listop_return def op_newlist(self, ll_newlist, lgt, default_val=None): res = self.do_call(ll_newlist, lgt) if (default_val is not None and isinstance(lltype.typeOf(default_val), lltype.Ptr)): - TP = lltype.typeOf(res).TO.OF + if hasattr(res, 'items'): + TP = lltype.typeOf(res.items).TO.OF + else: + TP = lltype.typeOf(res).TO.OF if default_val: default_val = lltype.cast_opaque_ptr(TP, res) else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sun Feb 15 15:03:16 2009 @@ -19,15 +19,16 @@ class ListDescr(BuiltinDescr): def __init__(self, getfunc, setfunc, malloc_func, append_func, - pop_func, insert_func, len_func, tp): - self.setfunc = setfunc - self.getfunc = getfunc - self.malloc_func = malloc_func - self.append_func = append_func - self.insert_func = insert_func - self.pop_func = pop_func - self.len_func = len_func - self.tp = tp + pop_func, insert_func, len_func, nonzero_func, tp): + self.setfunc = setfunc + self.getfunc = getfunc + self.malloc_func = malloc_func + self.append_func = append_func + self.insert_func = insert_func + self.pop_func = pop_func + self.len_func = len_func + self.nonzero_func = nonzero_func + self.tp = tp def equals(self, other): if isinstance(other, ListDescr): @@ -164,6 +165,9 @@ [lltype.Signed], TP) len_func, _ = support.builtin_func_for_spec(rtyper, 'list.len', [TP], lltype.Signed) + nonzero_func, _ = support.builtin_func_for_spec(rtyper, + 'list.nonzero', + [TP], lltype.Bool) if isinstance(TP.TO, lltype.GcStruct): append_func, _ = support.builtin_func_for_spec(rtyper, @@ -184,6 +188,7 @@ history.ConstAddr(append_func.value, self.cpu), history.ConstAddr(pop_func.value, self.cpu), history.ConstAddr(insert_func.value, self.cpu), + history.ConstAddr(nonzero_func.value, self.cpu), history.ConstAddr(len_func.value, self.cpu), tp) else: @@ -191,6 +196,7 @@ history.ConstAddr(setfunc.value, self.cpu), history.ConstAddr(malloc_func.value, self.cpu), None, None, None, + history.ConstAddr(nonzero_func.value, self.cpu), history.ConstAddr(len_func.value, self.cpu), tp) self.list_cache[TP.TO] = ld @@ -664,6 +670,8 @@ opname = 'len' elif oopspec_name == 'list.insert': opname = 'insert' + elif oopspec_name == 'list.nonzero': + opname = 'listnonzero' else: raise NotImplementedError("not supported %s" % oopspec_name) self.emit(opname) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 15:03:16 2009 @@ -375,7 +375,7 @@ field = instnode.known_length self.find_nodes_getfield(instnode, field, op.results[0]) continue - elif opname == 'len': + elif opname == 'len' or opname == 'listnonzero': instnode = self.getnode(op.args[1]) assert instnode.known_length != -1 lgtbox = op.results[0].constbox() @@ -697,7 +697,7 @@ ofs = instnode.known_length if self.optimize_getfield(instnode, ofs, op.results[0]): continue - elif opname == 'len': + elif opname == 'len' or opname == 'listnonzero': instnode = self.nodes[op.args[1]] assert instnode.known_length continue Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sun Feb 15 15:03:16 2009 @@ -426,6 +426,11 @@ args = [descr.len_func] + varargs self.execute_with_exc('len', args, 'int') + @arguments("builtin", "varargs") + def opimpl_listnonzero(self, descr, varargs): + args = [descr.nonzero_func] + varargs + self.execute_with_exc('listnonzero', args, 'int') + @arguments("indirectcallset", "box", "varargs") def opimpl_indirect_call(self, indirectcallset, box, varargs): assert isinstance(box, Const) # XXX Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Sun Feb 15 15:03:16 2009 @@ -111,6 +111,26 @@ assert res == f(33) self.check_all_virtualized() + def test_nonzero(self): + jitdriver = JitDriver(greens = [], reds = ['n']) + def f(n): + while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) + lst = [1, 2, 3] + lst.insert(0, n) + # nonzero should go away + if not lst: + return -33 + n = lst[0] - 1 + lst.pop() + # last pop is needed, otherwise it won't work + return n + res = self.meta_interp(f, [33]) + assert res == f(33) + self.check_all_virtualized() + self.check_loops(listnonzero=0, guard_true=1, guard_false=0) + def test_list_escapes(self): py.test.skip("XXX") def f(n): From fijal at codespeak.net Sun Feb 15 15:12:29 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 15:12:29 +0100 (CET) Subject: [pypy-svn] r61938 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090215141229.3E7671684B6@codespeak.net> Author: fijal Date: Sun Feb 15 15:12:28 2009 New Revision: 61938 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Log: oops, typo (and a check) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Sun Feb 15 15:12:28 2009 @@ -188,16 +188,16 @@ history.ConstAddr(append_func.value, self.cpu), history.ConstAddr(pop_func.value, self.cpu), history.ConstAddr(insert_func.value, self.cpu), - history.ConstAddr(nonzero_func.value, self.cpu), history.ConstAddr(len_func.value, self.cpu), + history.ConstAddr(nonzero_func.value, self.cpu), tp) else: ld = ListDescr(history.ConstAddr(getfunc.value, self.cpu), history.ConstAddr(setfunc.value, self.cpu), history.ConstAddr(malloc_func.value, self.cpu), None, None, None, - history.ConstAddr(nonzero_func.value, self.cpu), history.ConstAddr(len_func.value, self.cpu), + history.ConstAddr(nonzero_func.value, self.cpu), tp) self.list_cache[TP.TO] = ld return ld Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 15:12:28 2009 @@ -71,6 +71,7 @@ if isinstance(instnode.cls.source, ListDescr): ld = instnode.cls.source x = (alloc_offset + 1) << 16 + assert ofs < instnode.known_length self.setitems.append((ld.setfunc, x, ofs, num)) else: self.setfields.append((alloc_offset, ofs, num)) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Sun Feb 15 15:12:28 2009 @@ -44,6 +44,7 @@ assert res == 42 def test_accumulator(self): + py.test.skip("unsupported yet") path = py.path.local(tlc.__file__).dirpath('accumulator.tlc.src') code = path.read() res = self.exec_code(code, 20) From fijal at codespeak.net Sun Feb 15 16:21:18 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 16:21:18 +0100 (CET) Subject: [pypy-svn] r61939 - in pypy/branch/pyjitpl5/pypy/jit/tl: . test Message-ID: <20090215152118.2B89C168008@codespeak.net> Author: fijal Date: Sun Feb 15 16:21:16 2009 New Revision: 61939 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py Log: Rewrite tlc using virtualizables. It exposes more bugs in a jit (progress :) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/test/test_tlc.py Sun Feb 15 16:21:16 2009 @@ -1,5 +1,4 @@ import py -py.test.skip("Somehow broken") from pypy.jit.tl.tlopcode import compile, NEW, RETURN from pypy.jit.tl.test import test_tl from pypy.jit.tl.tlc import ConstantPool @@ -32,7 +31,7 @@ assert bytecode == bytecode2 assert pool == pool2 -class TestTLC(test_tl.TestTL): +class TestTLC(object): @staticmethod def interp(code='', pc=0, inputarg=0): from pypy.jit.tl.tlc import interp Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py Sun Feb 15 16:21:16 2009 @@ -216,30 +216,19 @@ t = -(-ord(c) & 0xff) return t -class FrameStack: - def __init__(self): - self.pc_stack = [] - self.args_stack = [] - self.stack_stack = [] - - def push(self, pc, args, stack): - self.pc_stack.append(pc) - self.args_stack.append(args) - self.stack_stack.append(stack) - return self - - def pop(self): - pc = self.pc_stack.pop() - args = self.args_stack.pop() - stack = self.stack_stack.pop() - return pc, args, stack +class Frame(object): + _virtualizable2_ = True - def isempty(self): - return len(self.pc_stack) == 0 + def __init__(self, args, pc): + assert isinstance(pc, int) + self.args = args + self.pc = pc + self.stack = [] def make_interp(supports_call, jitted=True): myjitdriver = JitDriver(greens = ['code', 'pc'], - reds = ['pool', 'args', 'stack', 'framestack']) + reds = ['frame', 'framestack', 'pool'], + virtualizables = ['frame']) def interp(code='', pc=0, inputarg=0, pool=None): if not isinstance(code,str): raise TypeError("code '%s' should be a string" % str(code)) @@ -250,14 +239,17 @@ return interp_eval(code, pc, args, pool).int_o() def interp_eval(code, pc, args, pool): - stack = [] - framestack = FrameStack() + assert isinstance(pc, int) + framestack = [] + frame = Frame(args, pc) + pc = frame.pc while pc < len(code): - myjitdriver.jit_merge_point(code=code, pc=pc, pool=pool, args=args, - stack=stack, framestack=framestack) + myjitdriver.jit_merge_point(frame=frame, framestack=framestack, + code=code, pc=pc, pool=pool) opcode = ord(code[pc]) pc += 1 + stack = frame.stack if opcode == NOP: pass @@ -355,10 +347,9 @@ pc += char2int(code[pc]) pc += 1 if old_pc > pc: - myjitdriver.can_enter_jit(code=code, pc=pc, pool=pool, - args=args, - stack=stack, - framestack=framestack) + myjitdriver.can_enter_jit(code=code, pc=pc, frame=frame, + framestack=framestack, + pool=pool) elif opcode == BR_COND: cond = stack.pop() @@ -366,10 +357,9 @@ old_pc = pc pc += char2int(code[pc]) + 1 if old_pc > pc: - myjitdriver.can_enter_jit(code=code, pc=pc, pool=pool, - args=args, - stack=stack, - framestack=framestack) + myjitdriver.can_enter_jit(code=code, pc=pc, frame=frame, + framestack=framestack, + pool=pool) else: pc += 1 @@ -379,38 +369,39 @@ old_pc = pc pc += offset if old_pc > pc: - myjitdriver.can_enter_jit(code=code, pc=pc, pool=pool, - args=args, - stack=stack, - framestack=framestack) + myjitdriver.can_enter_jit(code=code, pc=pc, frame=frame, + framestack=framestack, + pool=pool) elif supports_call and opcode == CALL: offset = char2int(code[pc]) pc += 1 - framestack.push(pc, args, stack) - pc = pc + offset - args = [zero] - stack = [] + frame.pc = pc + framestack.append(frame) + frame = Frame([zero], pc + offset) + pc = frame.pc elif opcode == RETURN: - if framestack.isempty(): + if not framestack: break if stack: res = stack.pop() else: res = None - pc, args, stack = framestack.pop() + frame = framestack.pop() + stack = frame.stack + pc = frame.pc if res: stack.append(res) elif opcode == PUSHARG: - stack.append(args[0]) + stack.append(frame.args[0]) elif opcode == PUSHARGN: idx = char2int(code[pc]) pc += 1 - stack.append(args[idx]) + stack.append(frame.args[idx]) elif opcode == NEW: idx = char2int(code[pc]) @@ -446,10 +437,10 @@ meth_args[num_args] = stack.pop() a = meth_args[0] meth_pc = a.send(name) - framestack.push(pc, args, stack) + frame.pc = pc + framestack.append(frame) + frame = Frame(meth_args, meth_pc) pc = meth_pc - args = meth_args - stack = [] elif opcode == PRINT: if not we_are_translated(): @@ -466,7 +457,7 @@ else: raise RuntimeError("unknown opcode: " + str(opcode)) - return stack[-1] + return frame.stack[-1] return interp, interp_eval From fijal at codespeak.net Sun Feb 15 17:15:43 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 15 Feb 2009 17:15:43 +0100 (CET) Subject: [pypy-svn] r61940 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090215161543.16BF1168485@codespeak.net> Author: fijal Date: Sun Feb 15 17:15:42 2009 New Revision: 61940 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Log: fix a bit of bugs Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Sun Feb 15 17:15:42 2009 @@ -284,6 +284,7 @@ if ofs >= field: instnode.curfields[ofs + 1] = node instnode.curfields[field] = fieldnode + instnode.known_length += 1 self.dependency_graph.append((instnode, fieldnode)) def find_nodes(self): @@ -344,6 +345,8 @@ if (isinstance(fieldbox, ConstInt) or self.nodes[op.args[2]].const): field = self.getsource(fieldbox).getint() + if field < 0: + field = instnode.known_length - field box = op.results[0] self.find_nodes_getfield(instnode, field, box) continue @@ -365,6 +368,8 @@ fieldbox = self.getsource(op.args[2]) assert isinstance(fieldbox, Const) or fieldbox.const field = fieldbox.getint() + if field < 0: + field = instnode.known_length - field self.find_nodes_insert(instnode, field, self.getnode(op.args[3])) continue @@ -378,16 +383,20 @@ continue elif opname == 'len' or opname == 'listnonzero': instnode = self.getnode(op.args[1]) - assert instnode.known_length != -1 - lgtbox = op.results[0].constbox() - self.nodes[op.results[0]] = InstanceNode(lgtbox, const=True) - continue + if not instnode.escaped: + assert instnode.known_length != -1 + lgtbox = op.results[0].constbox() + self.nodes[op.results[0]] = InstanceNode(lgtbox, const=True) + continue elif opname == 'setitem': instnode = self.getnode(op.args[1]) fieldbox = op.args[2] if (isinstance(fieldbox, ConstInt) or self.nodes[op.args[2]].const): field = self.getsource(fieldbox).getint() + if field < 0: + field = instnode.known_length - field + assert field < instnode.known_length self.find_nodes_setfield(instnode, field, self.getnode(op.args[3])) continue @@ -534,6 +543,8 @@ def optimize_getfield(self, instnode, ofs, box): if instnode.virtual or instnode.virtualized: + if ofs < 0: + ofs = instnode.known_length - ofs assert ofs in instnode.curfields return True # this means field is never actually elif ofs in instnode.cleanfields: @@ -558,6 +569,7 @@ if ofs >= field: instnode.curfields[ofs + 1] = node instnode.curfields[field] = valuenode + instnode.known_length += 1 def optimize_loop(self): self.ready_results = {} Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Sun Feb 15 17:15:42 2009 @@ -44,7 +44,7 @@ assert res == 42 def test_accumulator(self): - py.test.skip("unsupported yet") + py.test.skip("X") path = py.path.local(tlc.__file__).dirpath('accumulator.tlc.src') code = path.read() res = self.exec_code(code, 20) From afa at codespeak.net Mon Feb 16 13:42:39 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 16 Feb 2009 13:42:39 +0100 (CET) Subject: [pypy-svn] r61946 - pypy/trunk/pypy/rlib Message-ID: <20090216124239.7BB5516849F@codespeak.net> Author: afa Date: Mon Feb 16 13:42:36 2009 New Revision: 61946 Modified: pypy/trunk/pypy/rlib/rwin32.py Log: Translation fix on Windows: a function was missing Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Mon Feb 16 13:42:36 2009 @@ -94,6 +94,11 @@ LocalFree(buf[0]) return result + def lastWindowsError(): + code = GetLastError() + message = FormatError(code) + return WindowsError(code, message) + def FAILED(hr): return rffi.cast(HRESULT, hr) < 0 From afa at codespeak.net Mon Feb 16 13:47:29 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 16 Feb 2009 13:47:29 +0100 (CET) Subject: [pypy-svn] r61947 - in pypy/trunk/pypy/module: _codecs _codecs/test unicodedata Message-ID: <20090216124729.1B37D1684AA@codespeak.net> Author: afa Date: Mon Feb 16 13:47:28 2009 New Revision: 61947 Modified: pypy/trunk/pypy/module/_codecs/app_codecs.py pypy/trunk/pypy/module/_codecs/test/test_codecs.py pypy/trunk/pypy/module/unicodedata/__init__.py pypy/trunk/pypy/module/unicodedata/interp_ucd.py Log: Allow u'\N{NAME}' to return characters beyond the BMP on narrow unicode builds. Test and fix, should fix test_unicodedata on Windows. python2 is inconsistent here: it allows u'\N{CJK UNIFIED IDEOGRAPH-20000}' but not unichr(0x20000). Things will be better with python3. Modified: pypy/trunk/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/app_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/app_codecs.py Mon Feb 16 13:47:28 2009 @@ -749,13 +749,19 @@ message = "unknown Unicode character name" st = s[pos+1:look] try: - chr = unicodedata.lookup("%s" % st) + ch = unicodedata._get_code("%s" % st) except KeyError, e: x = unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-1, look+1) + p += x[0] + pos = x[1] else: - x = chr, look + 1 - p += x[0] - pos = x[1] + pos = look + 1 + if ch <= sys.maxunicode: + p += unichr(ch) + else: + ch -= 0x10000L + p += unichr(0xD800 + (ch >> 10)) + p += unichr(0xDC00 + (ch & 0x03FF)) else: x = unicode_call_errorhandler(errors, "unicodeescape", message, s, pos-1, look+1) else: Modified: pypy/trunk/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- pypy/trunk/pypy/module/_codecs/test/test_codecs.py (original) +++ pypy/trunk/pypy/module/_codecs/test/test_codecs.py Mon Feb 16 13:47:28 2009 @@ -44,6 +44,7 @@ assert unicode('\\N{SPACE}\\N{SPACE}','unicode-escape') == u" " assert unicode('\\N{SPACE}a\\N{SPACE}','unicode-escape') == u" a " assert "\\N{foo}xx".decode("unicode-escape", "ignore") == u"xx" + assert 1 <= len(u"\N{CJK UNIFIED IDEOGRAPH-20000}") <= 2 def test_literals(self): raises(UnicodeError, eval, 'u\'\\Uffffffff\'') Modified: pypy/trunk/pypy/module/unicodedata/__init__.py ============================================================================== --- pypy/trunk/pypy/module/unicodedata/__init__.py (original) +++ pypy/trunk/pypy/module/unicodedata/__init__.py Mon Feb 16 13:47:28 2009 @@ -13,6 +13,6 @@ } for name in '''lookup name decimal digit numeric category bidirectional east_asian_width combining mirrored decomposition - normalize'''.split(): + normalize _get_code'''.split(): interpleveldefs[name] = '''space.getattr(space.wrap(interp_ucd.ucd), space.wrap("%s"))''' % name Modified: pypy/trunk/pypy/module/unicodedata/interp_ucd.py ============================================================================== --- pypy/trunk/pypy/module/unicodedata/interp_ucd.py (original) +++ pypy/trunk/pypy/module/unicodedata/interp_ucd.py Mon Feb 16 13:47:28 2009 @@ -48,17 +48,20 @@ self.version = unicodedb.version - def lookup(self, space, name): + def _get_code(self, space, name): try: code = self._lookup(name.upper()) except KeyError: msg = space.mod(space.wrap("undefined character name '%s'"), space.wrap(name)) raise OperationError(space.w_KeyError, msg) + return space.wrap(code) + _get_code.unwrap_spec = ['self', ObjSpace, str] + + def lookup(self, space, name): return space.call_function(space.builtin.get('unichr'), - space.wrap(code)) - + self._get_code(space, name)) lookup.unwrap_spec = ['self', ObjSpace, str] - + def name(self, space, w_unichr, w_default=NoneNotWrapped): code = unichr_to_code_w(space, w_unichr) try: From fijal at codespeak.net Mon Feb 16 19:24:25 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 16 Feb 2009 19:24:25 +0100 (CET) Subject: [pypy-svn] r61953 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090216182425.3D23A1684ED@codespeak.net> Author: fijal Date: Mon Feb 16 19:24:23 2009 New Revision: 61953 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Tests and fixes Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Mon Feb 16 19:24:23 2009 @@ -37,7 +37,7 @@ self.setitems = [] def deal_with_box(self, box, nodes, liveboxes, memo, ready): - if isinstance(box, Const): + if isinstance(box, Const) or box not in nodes: virtual = False virtualized = False else: @@ -48,8 +48,6 @@ return memo[box] virtual = instnode.virtual virtualized = instnode.virtualized - if not virtual: - assert box in ready if virtual: if isinstance(instnode.cls.source, ListDescr): ld = instnode.cls.source @@ -112,14 +110,26 @@ self.expanded_fields = {} self.known_length = -1 + def set_known_length(self, val): + if val != -1: + print "Setting: %r to %d" % (self, val) + assert val >= -1 + self._kl = val + + def get_known_length(self): + return self._kl + + known_length = property(get_known_length, set_known_length) + def escape_if_startbox(self, memo): if self in memo: return memo[self] = None if self.startbox: self.escaped = True - for node in self.curfields.values(): - node.escape_if_startbox(memo) + if not self.virtualized: + for node in self.curfields.values(): + node.escape_if_startbox(memo) def add_to_dependency_graph(self, other, dep_graph): dep_graph.append((self, other)) @@ -149,11 +159,10 @@ XXX # XXX think fields = [] if self is other: - d = other.curfields + d = other.curfields.copy() d.update(self.origfields) else: d = other.curfields - d = other.curfields lst = d.items() lst.sort() for ofs, node in lst: @@ -284,7 +293,7 @@ if ofs >= field: instnode.curfields[ofs + 1] = node instnode.curfields[field] = fieldnode - instnode.known_length += 1 + instnode.known_length = instnode.known_length + 1 self.dependency_graph.append((instnode, fieldnode)) def find_nodes(self): @@ -308,20 +317,21 @@ instnode = InstanceNode(box, escaped=False) self.nodes[box] = instnode self.first_escaping_op = False - # XXX we don't support lists with variable length - assert isinstance(op.args[1], ConstInt) - instnode.known_length = op.args[1].getint() - # XXX following guard_builtin will set the - # correct class, otherwise it's a mess - continue + if (isinstance(op.args[1], ConstInt) or + self.nodes[op.args[1]].const): + instnode.known_length = self.getsource(op.args[1]).getint() + # XXX following guard_builtin will set the + # correct class, otherwise it's a mess + continue elif opname == 'guard_builtin': instnode = self.nodes[op.args[0]] # all builtins have equal classes instnode.cls = InstanceNode(op.args[1]) continue elif opname == 'guard_len': - instnode = self.nodes[op.args[0]] - instnode.known_length = op.args[1].getint() + if instnode.known_length == -1: + instnode = self.nodes[op.args[0]] + instnode.known_length = op.args[1].getint() continue elif opname == 'setfield_gc': instnode = self.getnode(op.args[0]) @@ -346,41 +356,47 @@ self.nodes[op.args[2]].const): field = self.getsource(fieldbox).getint() if field < 0: - field = instnode.known_length - field + field = instnode.known_length + field box = op.results[0] self.find_nodes_getfield(instnode, field, box) + print instnode, instnode.curfields, instnode.known_length continue else: instnode.escaped = True elif opname == 'append': instnode = self.getnode(op.args[1]) assert isinstance(instnode.cls.source, ListDescr) - assert instnode.known_length != -1 - field = instnode.known_length - instnode.known_length += 1 - self.find_nodes_setfield(instnode, field, - self.getnode(op.args[2])) + if instnode.known_length != -1: + field = instnode.known_length + instnode.known_length = instnode.known_length + 1 + self.find_nodes_setfield(instnode, field, + self.getnode(op.args[2])) + print instnode, instnode.curfields, instnode.known_length continue elif opname == 'insert': instnode = self.getnode(op.args[1]) assert isinstance(instnode.cls.source, ListDescr) - assert instnode.known_length != -1 - fieldbox = self.getsource(op.args[2]) - assert isinstance(fieldbox, Const) or fieldbox.const - field = fieldbox.getint() - if field < 0: - field = instnode.known_length - field - self.find_nodes_insert(instnode, field, - self.getnode(op.args[3])) + if instnode.known_length != -1: + fieldbox = self.getsource(op.args[2]) + assert isinstance(fieldbox, Const) or fieldbox.const + field = fieldbox.getint() + if field < 0: + field = instnode.known_length + field + self.find_nodes_insert(instnode, field, + self.getnode(op.args[3])) + print instnode, instnode.curfields, instnode.known_length continue elif opname == 'pop': instnode = self.getnode(op.args[1]) assert isinstance(instnode.cls.source, ListDescr) - assert instnode.known_length != -1 - instnode.known_length -= 1 - field = instnode.known_length - self.find_nodes_getfield(instnode, field, op.results[0]) - continue + if instnode.known_length != -1: + instnode.known_length = instnode.known_length - 1 + field = instnode.known_length + self.find_nodes_getfield(instnode, field, op.results[0]) + if field in instnode.curfields: + del instnode.curfields[field] + print instnode, instnode.curfields, instnode.known_length + continue elif opname == 'len' or opname == 'listnonzero': instnode = self.getnode(op.args[1]) if not instnode.escaped: @@ -395,10 +411,11 @@ or self.nodes[op.args[2]].const): field = self.getsource(fieldbox).getint() if field < 0: - field = instnode.known_length - field + field = instnode.known_length + field assert field < instnode.known_length self.find_nodes_setfield(instnode, field, self.getnode(op.args[3])) + print instnode, instnode.curfields, instnode.known_length continue else: instnode.escaped = True @@ -544,7 +561,7 @@ def optimize_getfield(self, instnode, ofs, box): if instnode.virtual or instnode.virtualized: if ofs < 0: - ofs = instnode.known_length - ofs + ofs = instnode.known_length + ofs assert ofs in instnode.curfields return True # this means field is never actually elif ofs in instnode.cleanfields: @@ -556,6 +573,8 @@ def optimize_setfield(self, instnode, ofs, valuenode, valuebox): if instnode.virtual or instnode.virtualized: + if ofs < 0: + ofs = instnode.known_length + ofs instnode.curfields[ofs] = valuenode else: assert not valuenode.virtual @@ -569,12 +588,13 @@ if ofs >= field: instnode.curfields[ofs + 1] = node instnode.curfields[field] = valuenode - instnode.known_length += 1 + instnode.known_length = instnode.known_length + 1 def optimize_loop(self): self.ready_results = {} newoperations = [] exception_might_have_happened = False + ops_so_far = [] mp = self.loop.operations[0] if mp.opname == 'merge_point': assert len(mp.args) == len(self.specnodes) @@ -588,6 +608,8 @@ assert not self.nodes[box].virtual for op in self.loop.operations: + ops_so_far.append(op) + if newoperations and newoperations[-1].results: self.ready_results[newoperations[-1].results[0]] = None opname = op.opname @@ -623,13 +645,13 @@ elif opname == 'guard_len': # it should be completely gone, because if it escapes # we don't virtualize it anymore - if not instnode.escaped: + if not instnode.escaped and instnode.known_length == -1: instnode = self.nodes[op.args[0]] instnode.known_length = op.args[1].getint() continue elif opname == 'guard_nonvirtualized': instnode = self.nodes[op.args[0]] - if instnode.virtualized: + if instnode.virtualized or instnode.virtual: continue op = self.optimize_guard(op) newoperations.append(op) @@ -680,40 +702,40 @@ if not instnode.escaped: instnode.virtual = True valuesource = self.getsource(op.args[2]) - assert isinstance(valuesource, Const) - maxlength = max(instnode.curfields.keys() + - instnode.origfields.keys()) - for i in range(maxlength + 1): - instnode.curfields[i] = InstanceNode(valuesource, - const=True) - for ofs, item in instnode.origfields.items(): - self.nodes[item.source] = instnode.curfields[ofs] instnode.known_length = op.args[1].getint() + curfields = {} + for i in range(instnode.known_length): + curfields[i] = InstanceNode(valuesource, + const=True) + instnode.curfields = curfields continue elif opname == 'append': instnode = self.nodes[op.args[1]] - valuenode = self.nodes[op.args[2]] - ofs = instnode.known_length - instnode.known_length += 1 - assert ofs != -1 - self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) - continue + valuenode = self.getnode(op.args[2]) + if instnode.virtual: + ofs = instnode.known_length + instnode.known_length = instnode.known_length + 1 + self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) + continue elif opname == 'insert': instnode = self.nodes[op.args[1]] - ofs = self.getsource(op.args[2]).getint() - valuenode = self.nodes[op.args[3]] - self.optimize_insert(instnode, ofs, valuenode, op.args[3]) - continue + if instnode.virtual: + ofs = self.getsource(op.args[2]).getint() + valuenode = self.nodes[op.args[3]] + self.optimize_insert(instnode, ofs, valuenode, op.args[3]) + continue elif opname == 'pop': instnode = self.nodes[op.args[1]] - instnode.known_length -= 1 - ofs = instnode.known_length - if self.optimize_getfield(instnode, ofs, op.results[0]): + if instnode.virtual: + instnode.known_length = instnode.known_length - 1 + ofs = instnode.known_length + if self.optimize_getfield(instnode, ofs, op.results[0]): + del instnode.curfields[ofs] continue elif opname == 'len' or opname == 'listnonzero': instnode = self.nodes[op.args[1]] - assert instnode.known_length - continue + if instnode.virtual: + continue elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Mon Feb 16 19:24:23 2009 @@ -44,7 +44,7 @@ assert res == 42 def test_accumulator(self): - py.test.skip("X") + py.test.skip("x") path = py.path.local(tlc.__file__).dirpath('accumulator.tlc.src') code = path.read() res = self.exec_code(code, 20) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Mon Feb 16 19:24:23 2009 @@ -69,7 +69,8 @@ jitdriver.can_enter_jit(n=n) jitdriver.jit_merge_point(n=n) l = [0] * 20 - x = l[3] + l[3] = 5 + x = l[-17] if n < 3: return x n -= 1 @@ -131,37 +132,62 @@ self.check_all_virtualized() self.check_loops(listnonzero=0, guard_true=1, guard_false=0) + def test_append_pop_rebuild(self): + jitdriver = JitDriver(greens = [], reds = ['n']) + def f(n): + while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) + lst = [] + lst.append(5) + lst.append(n) + lst[0] -= len(lst) + three = lst[0] + n = lst.pop() - three + if n == 2: + return n + lst.pop() + return n + res = self.meta_interp(f, [31]) + assert res == -2 + self.check_all_virtualized() + def test_list_escapes(self): - py.test.skip("XXX") + jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while True: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) lst = [] lst.append(n) n = lst.pop() - 3 if n < 0: return len(lst) - res = self.meta_interp(f, [31], exceptions=False) + res = self.meta_interp(f, [31]) assert res == 0 self.check_all_virtualized() def test_list_reenters(self): - py.test.skip("XXX") + jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) lst = [] lst.append(n) if n < 10: lst[-1] = n-1 n = lst.pop() - 3 return n - res = self.meta_interp(f, [31], exceptions=False) + res = self.meta_interp(f, [31]) assert res == -1 self.check_all_virtualized() def test_cannot_merge(self): - py.test.skip("XXX") + jitdriver = JitDriver(greens = [], reds = ['n']) def f(n): while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) lst = [] if n < 20: lst.append(n-3) @@ -169,10 +195,92 @@ lst.append(n-4) n = lst.pop() return n - res = self.meta_interp(f, [30], exceptions=False) + res = self.meta_interp(f, [30]) assert res == -1 self.check_all_virtualized() + def test_list_escapes(self): + jitdriver = JitDriver(greens = [], reds = ['n']) + def g(l): + pass + + def f(n): + while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) + l = [] + l.append(3) + g(l) + n -= 1 + return n + res = self.meta_interp(f, [30], policy=StopAtXPolicy(g)) + assert res == 0 + self.check_loops(append=1) + + def test_list_escapes_various_ops(self): + jitdriver = JitDriver(greens = [], reds = ['n']) + def g(l): + pass + + def f(n): + while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) + l = [] + l.append(3) + l.append(1) + n -= l.pop() + n -= l[0] + if l: + g(l) + n -= 1 + return n + res = self.meta_interp(f, [30], policy=StopAtXPolicy(g)) + assert res == 0 + self.check_loops(append=2) + + def test_list_escapes_find_nodes(self): + jitdriver = JitDriver(greens = [], reds = ['n']) + def g(l): + pass + + def f(n): + while n > 0: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) + l = [0] * n + l.append(3) + l.append(1) + n -= l.pop() + n -= l[-1] + if l: + g(l) + n -= 1 + return n + res = self.meta_interp(f, [30], policy=StopAtXPolicy(g)) + assert res == 0 + self.check_loops(append=2) + + def test_stuff_escapes_via_setitem(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'l']) + class Stuff(object): + def __init__(self, x): + self.x = x + + def f(n): + l = [None] + while n > 0: + jitdriver.can_enter_jit(n=n, l=l) + jitdriver.jit_merge_point(n=n, l=l) + s = Stuff(3) + l.append(s) + n -= l[0].x + return n + res = self.meta_interp(f, [30]) + assert res == 0 + self.check_loops(append=1) + + def test_extend(self): py.test.skip("XXX") def f(n): From antocuni at codespeak.net Mon Feb 16 23:52:43 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 16 Feb 2009 23:52:43 +0100 (CET) Subject: [pypy-svn] r61955 - in pypy/branch/oo-jit/pypy/jit/tl: . test Message-ID: <20090216225243.B7CC31684F6@codespeak.net> Author: antocuni Date: Mon Feb 16 23:52:41 2009 New Revision: 61955 Modified: pypy/branch/oo-jit/pypy/jit/tl/test/test_tl.py pypy/branch/oo-jit/pypy/jit/tl/test/test_tlc.py pypy/branch/oo-jit/pypy/jit/tl/tlc.py pypy/branch/oo-jit/pypy/jit/tl/tlopcode.py Log: a new opcode for tlc, to pass arguments to functions Modified: pypy/branch/oo-jit/pypy/jit/tl/test/test_tl.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/tl/test/test_tl.py (original) +++ pypy/branch/oo-jit/pypy/jit/tl/test/test_tl.py Mon Feb 16 23:52:41 2009 @@ -37,6 +37,7 @@ py.test.raises(RuntimeError, self.interp, list2bytecode([INVALID])) def test_tl_translatable(self): + py.test.skip('fixme, broken by r60900 :-(') code = list2bytecode([PUSH,42, PUSH,100, ADD]) fn = self.getcompiled(self.interp, [str, int, int]) assert self.interp(code, 0, 0) == fn(code, 0, 0) Modified: pypy/branch/oo-jit/pypy/jit/tl/test/test_tlc.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/tl/test/test_tlc.py (original) +++ pypy/branch/oo-jit/pypy/jit/tl/test/test_tlc.py Mon Feb 16 23:52:41 2009 @@ -270,6 +270,22 @@ res = interp_eval(bytecode, 0, [nil], pool) assert res.int_o() == 42 + def test_call_with_arguments(self): + from pypy.jit.tl.tlc import interp_eval, nil + pool = ConstantPool() + bytecode = compile(""" + PUSH 41 + CALLARGS foo/1 + RETURN + foo: + PUSHARG + PUSH 1 + ADD + RETURN + """, pool) + res = interp_eval(bytecode, 0, [nil], pool) + assert res.int_o() == 42 + def compile(self, filename): from pypy.jit.tl.tlc import interp_eval, IntObj pool = ConstantPool() Modified: pypy/branch/oo-jit/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/tl/tlc.py (original) +++ pypy/branch/oo-jit/pypy/jit/tl/tlc.py Mon Feb 16 23:52:41 2009 @@ -473,6 +473,20 @@ args = meth_args stack = [] + elif supports_call and opcode == CALLARGS: + offset = char2int(code[pc]) + pc += 1 + num_args = char2int(code[pc]) + call_args = [None] * num_args + while num_args > 0: + num_args -= 1 + call_args[num_args] = stack.pop() + hint(num_args, concrete=True) + framestack.push(pc, args, stack) + pc = pc + offset + args = call_args + stack = [] + elif opcode == PRINT: if not we_are_translated(): a = stack.pop() Modified: pypy/branch/oo-jit/pypy/jit/tl/tlopcode.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/tl/tlopcode.py (original) +++ pypy/branch/oo-jit/pypy/jit/tl/tlopcode.py Mon Feb 16 23:52:41 2009 @@ -54,6 +54,7 @@ opcode(33, "PRINT") opcode(34, "DUMP") opcode(35, "BR") +opcode(36, "CALLARGS") del opcode @@ -106,6 +107,12 @@ idx = pool.add_string(methname) bytecode.append(idx) bytecode.append(int(num_args)) + elif t[0] == 'CALLARGS': + # 'label/num_args' + fnname, num_args = arg.split('/') + label_usage.append( (fnname, len(bytecode)) ) + bytecode.append( 0 ) + bytecode.append(int(num_args)) else: # it's a label label_usage.append( (arg, len(bytecode)) ) From afa at codespeak.net Tue Feb 17 00:19:07 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Feb 2009 00:19:07 +0100 (CET) Subject: [pypy-svn] r61957 - pypy/trunk/pypy/rlib Message-ID: <20090216231907.09B5A16850E@codespeak.net> Author: afa Date: Tue Feb 17 00:19:06 2009 New Revision: 61957 Modified: pypy/trunk/pypy/rlib/rwin32.py Log: Correct a memory leak in rwin32.GetModuleFileName Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Tue Feb 17 00:19:06 2009 @@ -109,8 +109,11 @@ def GetModuleFileName(module): size = 255 # MAX_PATH buf = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - res = _GetModuleFileName(module, buf, size) - if not res: - return '' - else: - return ''.join([buf[i] for i in range(res)]) + try: + res = _GetModuleFileName(module, buf, size) + if not res: + return '' + else: + return ''.join([buf[i] for i in range(res)]) + finally: + lltype.free(buf, flavor='raw') From afa at codespeak.net Tue Feb 17 00:29:43 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Feb 2009 00:29:43 +0100 (CET) Subject: [pypy-svn] r61958 - in pypy/trunk/pypy: module/_rawffi module/_rawffi/test rlib rlib/test Message-ID: <20090216232943.2843F168465@codespeak.net> Author: afa Date: Tue Feb 17 00:29:42 2009 New Revision: 61958 Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py pypy/trunk/pypy/rlib/libffi.py pypy/trunk/pypy/rlib/test/test_libffi.py Log: Try harder not to embed the prebuilt name of the libc library, at least on Windows. Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Tue Feb 17 00:29:42 2009 @@ -496,6 +496,6 @@ def get_libc(space): try: - return space.wrap(W_CDLL(space, libc_name)) + return space.wrap(W_CDLL(space, get_libc_name())) except OSError, e: raise wrap_oserror(space, e) Modified: pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/test/test__rawffi.py Tue Feb 17 00:29:42 2009 @@ -165,11 +165,11 @@ prepare_c_example = staticmethod(prepare_c_example) def setup_class(cls): - from pypy.rlib.libffi import libc_name + from pypy.rlib.libffi import get_libc_name space = gettestobjspace(usemodules=('_rawffi', 'struct')) cls.space = space cls.w_lib_name = space.wrap(cls.prepare_c_example()) - cls.w_libc_name = space.wrap(libc_name) + cls.w_libc_name = space.wrap(get_libc_name()) if sys.platform == 'win32': cls.w_iswin32 = space.wrap(True) cls.w_libm_name = space.wrap('msvcrt') Modified: pypy/trunk/pypy/rlib/libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/libffi.py (original) +++ pypy/trunk/pypy/rlib/libffi.py Tue Feb 17 00:29:42 2009 @@ -256,6 +256,9 @@ pass # No check libc_name = ctypes.util.find_library('c') + def get_libc_name(): + return libc_name + del libc_name if _WIN32: def dlopen(name): @@ -314,9 +317,11 @@ get_libc_handle = external('get_libc_handle', [], rwin32.HANDLE) - libc_name = rwin32.GetModuleFileName(get_libc_handle()) - assert "msvcr" in libc_name.lower(), \ - "Suspect msvcrt library: %s" % (libc_name,) + def get_libc_name(): + return rwin32.GetModuleFileName(get_libc_handle()) + + assert "msvcr" in get_libc_name().lower(), \ + "Suspect msvcrt library: %s" % (get_libc_name(),) FFI_OK = cConfig.FFI_OK Modified: pypy/trunk/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/test/test_libffi.py (original) +++ pypy/trunk/pypy/rlib/test/test_libffi.py Tue Feb 17 00:29:42 2009 @@ -25,10 +25,10 @@ def test_dlopen(self): py.test.raises(OSError, "dlopen(rffi.str2charp('xxxxxxxxxxxx'))") - assert dlopen(rffi.str2charp(libc_name)) + assert dlopen(rffi.str2charp(get_libc_name())) def get_libc(self): - return CDLL(libc_name) + return CDLL(get_libc_name()) def get_libm(self): if sys.platform == 'win32': @@ -384,7 +384,7 @@ def test_get_libc_handle(self): handle = get_libc_handle() - print libc_name + print get_libc_name() print hex(handle) assert handle != 0 assert handle % 0x1000 == 0 From afa at codespeak.net Tue Feb 17 09:19:50 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Feb 2009 09:19:50 +0100 (CET) Subject: [pypy-svn] r61959 - pypy/trunk/pypy/rlib Message-ID: <20090217081950.1478B1684B6@codespeak.net> Author: afa Date: Tue Feb 17 09:19:49 2009 New Revision: 61959 Modified: pypy/trunk/pypy/rlib/libffi.py Log: Don't try to be smart when you can't test Modified: pypy/trunk/pypy/rlib/libffi.py ============================================================================== --- pypy/trunk/pypy/rlib/libffi.py (original) +++ pypy/trunk/pypy/rlib/libffi.py Tue Feb 17 09:19:49 2009 @@ -258,7 +258,6 @@ libc_name = ctypes.util.find_library('c') def get_libc_name(): return libc_name - del libc_name if _WIN32: def dlopen(name): From fijal at codespeak.net Tue Feb 17 09:55:48 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 17 Feb 2009 09:55:48 +0100 (CET) Subject: [pypy-svn] r61960 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090217085548.D2FA31684F2@codespeak.net> Author: fijal Date: Tue Feb 17 09:55:46 2009 New Revision: 61960 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Tests and fixes. Disable lazy list optimization for now (as it requires knowledge about append/pop operations as well) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Feb 17 09:55:46 2009 @@ -285,8 +285,8 @@ self.dependency_graph.append((instnode, fieldnode)) instnode.origfields[field] = fieldnode self.nodes[box] = fieldnode - if self.first_escaping_op: - instnode.expanded_fields[field] = None + #if self.first_escaping_op: + # instnode.expanded_fields[field] = None def find_nodes_insert(self, instnode, field, fieldnode): for ofs, node in instnode.curfields.items(): @@ -363,6 +363,9 @@ continue else: instnode.escaped = True + self.nodes[op.results[0]] = InstanceNode(op.results[0], + escaped=True) + continue elif opname == 'append': instnode = self.getnode(op.args[1]) assert isinstance(instnode.cls.source, ListDescr) @@ -397,6 +400,11 @@ del instnode.curfields[field] print instnode, instnode.curfields, instnode.known_length continue + self.nodes[op.results[0]] = InstanceNode(op.results[0], + escaped=True) + self.dependency_graph.append((instnode, + self.nodes[op.results[0]])) + continue elif opname == 'len' or opname == 'listnonzero': instnode = self.getnode(op.args[1]) if not instnode.escaped: @@ -415,9 +423,11 @@ assert field < instnode.known_length self.find_nodes_setfield(instnode, field, self.getnode(op.args[3])) - print instnode, instnode.curfields, instnode.known_length + print "XXX", instnode, " <- ", self.getnode(fieldbox) continue else: + self.dependency_graph.append((instnode, + self.getnode(op.args[3]))) instnode.escaped = True elif opname == 'guard_class': instnode = self.getnode(op.args[0]) @@ -712,21 +722,21 @@ elif opname == 'append': instnode = self.nodes[op.args[1]] valuenode = self.getnode(op.args[2]) - if instnode.virtual: + if not instnode.escaped: ofs = instnode.known_length instnode.known_length = instnode.known_length + 1 self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) continue elif opname == 'insert': instnode = self.nodes[op.args[1]] - if instnode.virtual: + if not instnode.escaped: ofs = self.getsource(op.args[2]).getint() valuenode = self.nodes[op.args[3]] self.optimize_insert(instnode, ofs, valuenode, op.args[3]) continue elif opname == 'pop': instnode = self.nodes[op.args[1]] - if instnode.virtual: + if not instnode.escaped: instnode.known_length = instnode.known_length - 1 ofs = instnode.known_length if self.optimize_getfield(instnode, ofs, op.results[0]): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Tue Feb 17 09:55:46 2009 @@ -44,7 +44,6 @@ assert res == 42 def test_accumulator(self): - py.test.skip("x") path = py.path.local(tlc.__file__).dirpath('accumulator.tlc.src') code = path.read() res = self.exec_code(code, 20) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Tue Feb 17 09:55:46 2009 @@ -279,7 +279,25 @@ res = self.meta_interp(f, [30]) assert res == 0 self.check_loops(append=1) - + + def test_virtual_escaping_via_list(self): + jitdriver = JitDriver(greens = [], reds = ['n', 'l']) + class Stuff(object): + def __init__(self, x): + self.x = x + + def f(n): + l = [Stuff(n-i) for i in range(n)] + + while n > 0: + jitdriver.can_enter_jit(n=n, l=l) + jitdriver.jit_merge_point(n=n, l=l) + s = l.pop() + n -= s.x + + res = self.meta_interp(f, [20]) + assert res == f(20) + self.check_loops(pop=1, getfield_gc=1) def test_extend(self): py.test.skip("XXX") From fijal at codespeak.net Tue Feb 17 10:03:22 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 17 Feb 2009 10:03:22 +0100 (CET) Subject: [pypy-svn] r61962 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090217090322.8619A1684EA@codespeak.net> Author: fijal Date: Tue Feb 17 10:03:22 2009 New Revision: 61962 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: add a comment (not yet failing test) what is wrong Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Feb 17 10:03:22 2009 @@ -865,6 +865,9 @@ storage = guard_op.storage_info for vtable in storage.allocations: + # XXX virtual object that came from the outside (stored on + # a virtualizable) has no entry in type_cache, probably + # we need to attach some info to guard_class sizebox = ConstInt(type_cache.class_size[vtable]) vtablebox = ConstInt(vtable) [instbox] = history.execute_and_record('new_with_vtable', From fijal at codespeak.net Tue Feb 17 10:04:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 17 Feb 2009 10:04:23 +0100 (CET) Subject: [pypy-svn] r61963 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090217090423.26FCD1684EF@codespeak.net> Author: fijal Date: Tue Feb 17 10:04:22 2009 New Revision: 61963 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py Log: a bit weird - attach framestack to virtualizable to promise noone from the outside is playing with our framestack Modified: pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/tlc.py Tue Feb 17 10:04:22 2009 @@ -224,11 +224,17 @@ self.args = args self.pc = pc self.stack = [] + +class Framestack(object): + _virtualizable2_ = True + + def __init__(self): + self.s = [] def make_interp(supports_call, jitted=True): myjitdriver = JitDriver(greens = ['code', 'pc'], reds = ['frame', 'framestack', 'pool'], - virtualizables = ['frame']) + virtualizables = ['frame', 'framestack']) def interp(code='', pc=0, inputarg=0, pool=None): if not isinstance(code,str): raise TypeError("code '%s' should be a string" % str(code)) @@ -240,7 +246,7 @@ def interp_eval(code, pc, args, pool): assert isinstance(pc, int) - framestack = [] + framestack = Framestack() frame = Frame(args, pc) pc = frame.pc @@ -378,18 +384,18 @@ offset = char2int(code[pc]) pc += 1 frame.pc = pc - framestack.append(frame) + framestack.s.append(frame) frame = Frame([zero], pc + offset) pc = frame.pc elif opcode == RETURN: - if not framestack: + if not framestack.s: break if stack: res = stack.pop() else: res = None - frame = framestack.pop() + frame = framestack.s.pop() stack = frame.stack pc = frame.pc if res: @@ -438,7 +444,7 @@ a = meth_args[0] meth_pc = a.send(name) frame.pc = pc - framestack.append(frame) + framestack.s.append(frame) frame = Frame(meth_args, meth_pc) pc = meth_pc From antocuni at codespeak.net Tue Feb 17 12:02:49 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 17 Feb 2009 12:02:49 +0100 (CET) Subject: [pypy-svn] r61964 - pypy/branch/oo-jit/pypy/jit/codegen/i386 Message-ID: <20090217110249.01354168510@codespeak.net> Author: antocuni Date: Tue Feb 17 12:02:47 2009 New Revision: 61964 Modified: pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py Log: don't compute TotalOrderSymbolics too early Modified: pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/i386/ri386.py Tue Feb 17 12:02:47 2009 @@ -1,5 +1,6 @@ from pypy.rlib.rarithmetic import intmask from pypy.rlib.objectmodel import ComputedIntSymbolic, CDefinedIntSymbolic +from pypy.rpython.normalizecalls import TotalOrderSymbolic class OPERAND(object): _attrs_ = [] @@ -244,6 +245,8 @@ rel32 = REL32 def imm(value): + if isinstance(value, TotalOrderSymbolic): + raise TypeError # XXX? if isinstance(value, ComputedIntSymbolic): value = value.compute_fn() elif isinstance(value, CDefinedIntSymbolic): From afa at codespeak.net Tue Feb 17 13:10:25 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Feb 2009 13:10:25 +0100 (CET) Subject: [pypy-svn] r61966 - pypy/trunk/pypy/lib/_ctypes Message-ID: <20090217121025.C27781684B6@codespeak.net> Author: afa Date: Tue Feb 17 13:10:24 2009 New Revision: 61966 Modified: pypy/trunk/pypy/lib/_ctypes/__init__.py pypy/trunk/pypy/lib/_ctypes/array.py pypy/trunk/pypy/lib/_ctypes/basics.py pypy/trunk/pypy/lib/_ctypes/function.py pypy/trunk/pypy/lib/_ctypes/primitive.py pypy/trunk/pypy/lib/_ctypes/structure.py pypy/trunk/pypy/lib/_ctypes/union.py Log: ctypes: More correct support for OUT parameters: - __ctypes_from_outparam__ is used only for out parameters, not for return values - pass the byref() to the function, but returns the base object at the end. Modified: pypy/trunk/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/__init__.py (original) +++ pypy/trunk/pypy/lib/_ctypes/__init__.py Tue Feb 17 13:10:24 2009 @@ -16,6 +16,7 @@ if _os.name in ("nt", "ce"): from _rawffi import FormatError from _rawffi import check_HRESULT as _check_HRESULT + CopyComPointer = None # XXX from _rawffi import FUNCFLAG_STDCALL, FUNCFLAG_CDECL, FUNCFLAG_PYTHONAPI Modified: pypy/trunk/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/array.py (original) +++ pypy/trunk/pypy/lib/_ctypes/array.py Tue Feb 17 13:10:24 2009 @@ -85,7 +85,7 @@ res._buffer = ffiarray res._base = base res._index = index - return res.__ctypes_from_outparam__() + return res def _CData_retval(self, resbuffer): raise NotImplementedError Modified: pypy/trunk/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/basics.py (original) +++ pypy/trunk/pypy/lib/_ctypes/basics.py Tue Feb 17 13:10:24 2009 @@ -71,7 +71,7 @@ res.__dict__['_buffer'] = resbuffer res.__dict__['_base'] = base res.__dict__['_index'] = index - return res.__ctypes_from_outparam__() + return res def _CData_retval(self, resbuffer): return self._CData_output(resbuffer) Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Tue Feb 17 13:10:24 2009 @@ -230,11 +230,17 @@ for i, argtype in enumerate(argtypes): if i > 0 and self._paramflags is not None: idlflag, name = self._paramflags[i-1] - if idlflag == 2: # OUT + if idlflag == 1: # IN + pass + elif idlflag == 2: # OUT import ctypes - arg = ctypes.byref(argtype._type_()) - wrapped_args.append((arg, arg)) + val = argtype._type_() + wrapped = (val, ctypes.byref(val)) + wrapped_args.append(wrapped) continue + else: + raise NotImplementedError( + "paramflags = %s" % (self._paramflags[i-1],)) if consumed == len(args): raise TypeError("Not enough arguments") @@ -282,18 +288,17 @@ results = [] if self._paramflags: - for argtype, (_, obj), paramflag in zip(argtypes[1:], argsandobjs[1:], + for argtype, (obj, _), paramflag in zip(argtypes[1:], argsandobjs[1:], self._paramflags): idlflag, name = paramflag - if idlflag == 2: # OUT - val = obj.contents - - # XXX find a better way to detect pointers to pointers - basetype = argtype._type_._type_ - if isinstance(basetype, str) and basetype != 'P': - val = val.value - + if idlflag == 1: # IN + pass + elif idlflag == 2: # OUT + val = obj.__ctypes_from_outparam__() results.append(val) + else: + raise NotImplementedError( + "paramflags = %s" % (paramflag,)) if results: if len(results) == 1: Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/primitive.py (original) +++ pypy/trunk/pypy/lib/_ctypes/primitive.py Tue Feb 17 13:10:24 2009 @@ -257,6 +257,10 @@ except (TypeError, ValueError): return super(SimpleType, self).from_param(value) + def _CData_output(self, resbuffer, base=None, index=-1): + output = super(SimpleType, self)._CData_output(resbuffer, base, index) + return output.value + def _sizeofinstances(self): return _rawffi.sizeof(self._type_) @@ -287,6 +291,10 @@ del _getvalue, _setvalue def __ctypes_from_outparam__(self): + meta = type(type(self)) + if issubclass(meta, SimpleType) and meta != SimpleType: + return self + return self.value def __repr__(self): Modified: pypy/trunk/pypy/lib/_ctypes/structure.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/structure.py (original) +++ pypy/trunk/pypy/lib/_ctypes/structure.py Tue Feb 17 13:10:24 2009 @@ -140,14 +140,14 @@ res.__dict__['_buffer'] = ffistruct res.__dict__['_base'] = base res.__dict__['_index'] = index - return res.__ctypes_from_outparam__() + return res def _CData_retval(self, resbuffer): res = self.__new__(self) res.__dict__['_buffer'] = resbuffer res.__dict__['_base'] = None res.__dict__['_index'] = -1 - return res.__ctypes_from_outparam__() + return res class Structure(_CData): __metaclass__ = StructureMeta Modified: pypy/trunk/pypy/lib/_ctypes/union.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/union.py (original) +++ pypy/trunk/pypy/lib/_ctypes/union.py Tue Feb 17 13:10:24 2009 @@ -72,14 +72,14 @@ res.__dict__['_buffer'] = ffiopaque res.__dict__['_base'] = base res.__dict__['_index'] = index - return res.__ctypes_from_outparam__() + return res def _CData_retval(self, resbuffer): res = self.__new__(self) res.__dict__['_buffer'] = resbuffer res.__dict__['_base'] = None res.__dict__['_index'] = -1 - return res.__ctypes_from_outparam__() + return res class Union(_CData): From afa at codespeak.net Tue Feb 17 13:42:24 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Feb 2009 13:42:24 +0100 (CET) Subject: [pypy-svn] r61967 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090217124224.2F1F2168451@codespeak.net> Author: afa Date: Tue Feb 17 13:42:20 2009 New Revision: 61967 Modified: pypy/trunk/pypy/objspace/std/test/test_ropeobject.py pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py Log: These tests need our unicodedata module, because the \N{} constructs now use the special unicodedata._get_code() function, which returns an integer and can handle characters outside the BMP even on a narrow unicode build. Modified: pypy/trunk/pypy/objspace/std/test/test_ropeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_ropeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_ropeobject.py Tue Feb 17 13:42:20 2009 @@ -78,7 +78,8 @@ class AppTestUnicodeRope(test_unicodeobject.AppTestUnicodeString): def setup_class(cls): - cls.space = gettestobjspace(**{"objspace.std.withrope": True}) + cls.space = gettestobjspace(usemodules=('unicodedata',), + **{"objspace.std.withrope": True}) def test_rfind_corner_case(self): skip("XXX Fix") Modified: pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_ropeunicodeobject.py Tue Feb 17 13:42:20 2009 @@ -38,7 +38,8 @@ class AppTestUnicodeRope(test_unicodeobject.AppTestUnicodeString): def setup_class(cls): - cls.space = gettestobjspace(**{"objspace.std.withropeunicode": True}) + cls.space = gettestobjspace(usemodules=('unicodedata',), + **{"objspace.std.withropeunicode": True}) def test_replace_buffer(self): skip("XXX fix") Modified: pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_unicodeobject.py Tue Feb 17 13:42:20 2009 @@ -1,5 +1,6 @@ import py import sys +from pypy.conftest import gettestobjspace class TestUnicodeObject: @@ -40,7 +41,8 @@ class AppTestUnicodeString: def setup_class(cls): - import sys + space = gettestobjspace(usemodules=('unicodedata',)) + cls.space = space cls.w_version_info = cls.space.wrap(sys.version_info) def test_addition(self): From antocuni at codespeak.net Tue Feb 17 14:05:09 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 17 Feb 2009 14:05:09 +0100 (CET) Subject: [pypy-svn] r61970 - pypy/branch/oo-jit/pypy/jit/rainbow/test Message-ID: <20090217130509.F3484168452@codespeak.net> Author: antocuni Date: Tue Feb 17 14:05:09 2009 New Revision: 61970 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_0tlc.py Log: this test passes nowadays Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_0tlc.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_0tlc.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_0tlc.py Tue Feb 17 14:05:09 2009 @@ -106,7 +106,6 @@ #self.check_insns(...) def test_bug(self): - py.test.skip('fix me') code = """ NEW foo,meth=meth PUSHARG # if we use PUSH it works From afa at codespeak.net Tue Feb 17 14:42:20 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Feb 2009 14:42:20 +0100 (CET) Subject: [pypy-svn] r61972 - in pypy/trunk/pypy: lib/_ctypes lib/app_test/ctypes_tests module/_rawffi Message-ID: <20090217134220.804B716845E@codespeak.net> Author: afa Date: Tue Feb 17 14:42:17 2009 New Revision: 61972 Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py pypy/trunk/pypy/lib/app_test/ctypes_tests/test_win32.py pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Log: Add support for the ctypes.wintypes.VARIANT_BOOL type Modified: pypy/trunk/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/primitive.py (original) +++ pypy/trunk/pypy/lib/_ctypes/primitive.py Tue Feb 17 14:42:17 2009 @@ -239,6 +239,16 @@ self._buffer[0] = value result.value = property(_getvalue, _setvalue) + elif tp == 'v': # VARIANT_BOOL type + def _getvalue(self): + return bool(self._buffer[0]) + def _setvalue(self, value): + if value: + self._buffer[0] = -1 # VARIANT_TRUE + else: + self._buffer[0] = 0 # VARIANT_FALSE + result.value = property(_getvalue, _setvalue) + return result from_address = cdata_from_address Modified: pypy/trunk/pypy/lib/app_test/ctypes_tests/test_win32.py ============================================================================== --- pypy/trunk/pypy/lib/app_test/ctypes_tests/test_win32.py (original) +++ pypy/trunk/pypy/lib/app_test/ctypes_tests/test_win32.py Tue Feb 17 14:42:17 2009 @@ -52,6 +52,13 @@ assert ex.details == ("details",) assert (ex.hresult, ex.text, ex.details) == ex[:] + def test_VARIANT(self): + from ctypes import wintypes + a = wintypes.VARIANT_BOOL() + assert a.value is False + b = wintypes.VARIANT_BOOL(3) + assert b.value is True + class TestStructures(BaseCTypesTestChecker): def test_struct_by_value(self): Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Tue Feb 17 14:42:17 2009 @@ -77,6 +77,7 @@ if _MS_WINDOWS: LL_TYPEMAP['X'] = rffi.CCHARP + LL_TYPEMAP['v'] = rffi.SHORT def letter2tp(space, key): try: @@ -225,7 +226,7 @@ buffer.""" # xxx fix doc ) -unroll_letters_for_numbers = unrolling_iterable("bBhHiIlLqQ") +unroll_letters_for_numbers = unrolling_iterable("bBhHiIlLqQv") def segfault_exception(space, reason): w_mod = space.getbuiltinmodule("_rawffi") From afa at codespeak.net Tue Feb 17 18:31:44 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Feb 2009 18:31:44 +0100 (CET) Subject: [pypy-svn] r61976 - pypy/trunk/pypy/lib/_ctypes Message-ID: <20090217173144.7CB8E16852F@codespeak.net> Author: afa Date: Tue Feb 17 18:31:43 2009 New Revision: 61976 Modified: pypy/trunk/pypy/lib/_ctypes/function.py Log: Great progress towards a fully working comtypes module. Now pypy can start and control an Excel application! >>>> from comtypes.client import CreateObject >>>> xl = CreateObject("Excel.Application") # Generating comtypes.gen._00020813_0000_0000_C000_000000000046_0_1_3 # Generating comtypes.gen._00020430_0000_0000_C000_000000000046_0_2_0 # Generating comtypes.gen.stdole # Generating comtypes.gen._2DF8D04C_5BFA_101B_BDE5_00AA0044DE52_0_2_1 # Generating comtypes.gen.Office # Generating comtypes.gen._0002E157_0000_0000_C000_000000000046_0_5_3 # Generating comtypes.gen.VBIDE # Generating comtypes.gen.Excel >>>> xl.Workbooks.Add() >>>> xl.Range("A1", "C1") = (10, 20, 30) >>>> xl.Range("D1").Formula = "=SUM(A1:C1)" >>>> print xl.Range("D1").Value 60.0 On the implementation side: it seems that ctypes has grown features specially for comtypes. Most of these features are difficult to test without a full COM client. Modified: pypy/trunk/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/function.py (original) +++ pypy/trunk/pypy/lib/_ctypes/function.py Tue Feb 17 18:31:43 2009 @@ -6,6 +6,15 @@ # XXX this file needs huge refactoring I fear +PARAMFLAG_FIN = 0x1 +PARAMFLAG_FOUT = 0x2 +PARAMFLAG_FLCID = 0x4 +def get_com_error(errcode, riid, pIunk): + "Win32 specific: build a COM Error exception" + # XXX need C support code + from _ctypes import COMError + return COMError(errcode, None, None) + class CFuncPtrType(_CDataMeta): # XXX write down here defaults and such things @@ -228,23 +237,45 @@ wrapped_args = [] consumed = 0 for i, argtype in enumerate(argtypes): + defaultvalue = None if i > 0 and self._paramflags is not None: - idlflag, name = self._paramflags[i-1] - if idlflag == 1: # IN + paramflag = self._paramflags[i-1] + if len(paramflag) == 2: + idlflag, name = paramflag + elif len(paramflag) == 3: + idlflag, name, defaultvalue = paramflag + else: + idlflag = 0 + idlflag &= (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID) + + if idlflag in (0, PARAMFLAG_FIN): pass - elif idlflag == 2: # OUT + elif idlflag == PARAMFLAG_FOUT: import ctypes val = argtype._type_() wrapped = (val, ctypes.byref(val)) wrapped_args.append(wrapped) continue + elif idlflag == PARAMFLAG_FIN | PARAMFLAG_FLCID: + # Always taken from defaultvalue if given, + # else the integer 0. + val = defaultvalue + if val is None: + val = 0 + wrapped = argtype._CData_input(val) + wrapped_args.append(wrapped) + continue else: raise NotImplementedError( "paramflags = %s" % (self._paramflags[i-1],)) - if consumed == len(args): + if consumed < len(args): + arg = args[consumed] + elif defaultvalue is not None: + arg = defaultvalue + else: raise TypeError("Not enough arguments") - arg = args[consumed] + try: wrapped = argtype._CData_input(arg) except (UnicodeError, TypeError), e: @@ -272,7 +303,13 @@ retval = None - if restype is not None: + if self._com_index: + if resbuffer[0] & 0x80000000: + raise get_com_error(resbuffer[0], + self._com_iid, argsandobjs[0][0]) + else: + retval = int(resbuffer[0]) + elif restype is not None: checker = getattr(self.restype, '_check_retval_', None) if checker: val = restype(resbuffer[0]) @@ -285,17 +322,26 @@ retval = restype(resbuffer[0]) else: retval = restype._CData_retval(resbuffer) - + results = [] if self._paramflags: for argtype, (obj, _), paramflag in zip(argtypes[1:], argsandobjs[1:], self._paramflags): - idlflag, name = paramflag - if idlflag == 1: # IN + if len(paramflag) == 2: + idlflag, name = paramflag + elif len(paramflag) == 3: + idlflag, name, defaultvalue = paramflag + else: + idlflag = 0 + idlflag &= (PARAMFLAG_FIN | PARAMFLAG_FOUT | PARAMFLAG_FLCID) + + if idlflag in (0, PARAMFLAG_FIN): pass - elif idlflag == 2: # OUT + elif idlflag == PARAMFLAG_FOUT: val = obj.__ctypes_from_outparam__() results.append(val) + elif idlflag == PARAMFLAG_FIN | PARAMFLAG_FLCID: + pass else: raise NotImplementedError( "paramflags = %s" % (paramflag,)) From afa at codespeak.net Tue Feb 17 18:32:49 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 17 Feb 2009 18:32:49 +0100 (CET) Subject: [pypy-svn] r61977 - pypy/trunk/pypy/lib/_ctypes Message-ID: <20090217173249.ED79B16852F@codespeak.net> Author: afa Date: Tue Feb 17 18:32:49 2009 New Revision: 61977 Modified: pypy/trunk/pypy/lib/_ctypes/basics.py Log: comtypes needs these attributes. I'm not sure to have set them correctly, though. I could not find any use of them anywhere else. Modified: pypy/trunk/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/trunk/pypy/lib/_ctypes/basics.py (original) +++ pypy/trunk/pypy/lib/_ctypes/basics.py Tue Feb 17 18:32:49 2009 @@ -127,6 +127,11 @@ def __buffer__(self): return buffer(self._buffer) + def _get_b_base(self): + return self._objects + _b_base_ = property(_get_b_base) + _b_needsfree_ = False + def sizeof(tp): if not isinstance(tp, _CDataMeta): if isinstance(tp, _CData): From afa at codespeak.net Wed Feb 18 11:15:35 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 18 Feb 2009 11:15:35 +0100 (CET) Subject: [pypy-svn] r61998 - in pypy/trunk/pypy/interpreter: . test Message-ID: <20090218101535.CCEEE168512@codespeak.net> Author: afa Date: Wed Feb 18 11:15:35 2009 New Revision: 61998 Modified: pypy/trunk/pypy/interpreter/argument.py pypy/trunk/pypy/interpreter/test/test_function.py Log: When calling a function with the incorrect number of parameters, don't add the number of "blind" arguments to the error message. otherwise you get misleading error messages like: >>>> len() TypeError: len() takes exactly 1 argument (1 given) Modified: pypy/trunk/pypy/interpreter/argument.py ============================================================================== --- pypy/trunk/pypy/interpreter/argument.py (original) +++ pypy/trunk/pypy/interpreter/argument.py Wed Feb 18 11:15:35 2009 @@ -257,11 +257,11 @@ avail = upfront + self.nargs if avail + len(defaults_w) < co_argcount: - raise ArgErrCount(blindargs + self.nargs , 0, + raise ArgErrCount(self.nargs , 0, (co_argcount, has_vararg, has_kwarg), defaults_w, co_argcount - avail - len(defaults_w)) if avail > co_argcount and not has_vararg: - raise ArgErrCount(blindargs + self.nargs, 0, + raise ArgErrCount(self.nargs, 0, (co_argcount, has_vararg, has_kwarg), defaults_w, 0) Modified: pypy/trunk/pypy/interpreter/test/test_function.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_function.py (original) +++ pypy/trunk/pypy/interpreter/test/test_function.py Wed Feb 18 11:15:35 2009 @@ -197,6 +197,21 @@ raises(TypeError, len, s, some_unknown_keyword=s) raises(TypeError, len, s, s, some_unknown_keyword=s) + def test_call_error_message(self): + try: + len() + except TypeError, e: + assert "len() takes exactly 1 argument (0 given)" in e.message + else: + assert 0, "did not raise" + + try: + len(1, 2) + except TypeError, e: + assert "len() takes exactly 1 argument (2 given)" in e.message + else: + assert 0, "did not raise" + def test_unicode_docstring(self): def f(): u"hi" From afa at codespeak.net Wed Feb 18 11:27:10 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 18 Feb 2009 11:27:10 +0100 (CET) Subject: [pypy-svn] r62000 - pypy/trunk/pypy/module/_rawffi Message-ID: <20090218102710.3D7C3168528@codespeak.net> Author: afa Date: Wed Feb 18 11:27:09 2009 New Revision: 62000 Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Log: Fix translation on Unix: the letter 'v' should be set only on Windows. Modified: pypy/trunk/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/trunk/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/trunk/pypy/module/_rawffi/interp_rawffi.py Wed Feb 18 11:27:09 2009 @@ -41,11 +41,13 @@ 'Z' : ffi_type_pointer, } TYPEMAP_PTR_LETTERS = "POszZ" +TYPEMAP_NUMBER_LETTERS = "bBhHiIlLqQ" if _MS_WINDOWS: TYPEMAP['X'] = ffi_type_pointer TYPEMAP['v'] = ffi_type_sshort TYPEMAP_PTR_LETTERS += 'X' + TYPEMAP_NUMBER_LETTERS += 'v' def size_alignment(ffi_type): return intmask(ffi_type.c_size), intmask(ffi_type.c_alignment) @@ -226,7 +228,7 @@ buffer.""" # xxx fix doc ) -unroll_letters_for_numbers = unrolling_iterable("bBhHiIlLqQv") +unroll_letters_for_numbers = unrolling_iterable(TYPEMAP_NUMBER_LETTERS) def segfault_exception(space, reason): w_mod = space.getbuiltinmodule("_rawffi") From antocuni at codespeak.net Wed Feb 18 16:16:54 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 18 Feb 2009 16:16:54 +0100 (CET) Subject: [pypy-svn] r62010 - pypy/branch/oo-jit/pypy/jit/tl Message-ID: <20090218151654.E366C16851D@codespeak.net> Author: antocuni Date: Wed Feb 18 16:16:54 2009 New Revision: 62010 Modified: pypy/branch/oo-jit/pypy/jit/tl/tlc.py Log: translation fix Modified: pypy/branch/oo-jit/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/tl/tlc.py (original) +++ pypy/branch/oo-jit/pypy/jit/tl/tlc.py Wed Feb 18 16:16:54 2009 @@ -466,7 +466,10 @@ meth_args[num_args] = stack.pop() hint(num_args, concrete=True) a = meth_args[0] + # XXX: if you uncomment the next line, + # test_0tlc.test_expr fails hint(a, promote_class=True) + meth_pc = hint(a.send(name), promote=True) framestack.push(pc, args, stack) pc = meth_pc @@ -477,13 +480,14 @@ offset = char2int(code[pc]) pc += 1 num_args = char2int(code[pc]) + pc += 1 call_args = [None] * num_args while num_args > 0: num_args -= 1 call_args[num_args] = stack.pop() hint(num_args, concrete=True) framestack.push(pc, args, stack) - pc = pc + offset + pc = pc + offset - 1 args = call_args stack = [] From antocuni at codespeak.net Wed Feb 18 16:34:43 2009 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 18 Feb 2009 16:34:43 +0100 (CET) Subject: [pypy-svn] r62011 - pypy/branch/oo-jit/pypy/jit/tl Message-ID: <20090218153443.B3CD31684F9@codespeak.net> Author: antocuni Date: Wed Feb 18 16:34:43 2009 New Revision: 62011 Modified: pypy/branch/oo-jit/pypy/jit/tl/tlc.py Log: (in-progress) try to get rid of framestack&co, because the merging logic seems not to like them. Maybe this checkin will be reverted Modified: pypy/branch/oo-jit/pypy/jit/tl/tlc.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/tl/tlc.py (original) +++ pypy/branch/oo-jit/pypy/jit/tl/tlc.py Wed Feb 18 16:34:43 2009 @@ -266,6 +266,10 @@ code_len = len(code) pool = hint(hint(pool2, concrete=True), deepfreeze=True) stack = [] + pc_stack = [] + args_stack = [] + stack_stack = [] + framestack = FrameStack() while pc < code_len: @@ -410,14 +414,19 @@ stack = [] elif opcode == RETURN: - if framestack.isempty(): + #if framestack.isempty(): + if len(pc_stack) == 0: break if stack: res = stack.pop() else: res = None - pc2, args, stack = framestack.pop() - pc = hint(pc2, promote=True) + #pc2, args, stack = framestack.pop() + #pc = hint(pc2, promote=True) + pc3 = pc_stack.pop() + pc = hint(pc3, promote=True) + args = args_stack.pop() + stack = stack_stack.pop() if res: stack.append(res) @@ -486,7 +495,10 @@ num_args -= 1 call_args[num_args] = stack.pop() hint(num_args, concrete=True) - framestack.push(pc, args, stack) + #framestack.push(pc, args, stack) + pc_stack.append(pc) + args_stack.append(args) + stack_stack.append(stack) pc = pc + offset - 1 args = call_args stack = [] From afa at codespeak.net Thu Feb 19 01:39:08 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 01:39:08 +0100 (CET) Subject: [pypy-svn] r62017 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219003908.21B21169E0F@codespeak.net> Author: afa Date: Thu Feb 19 01:39:06 2009 New Revision: 62017 Added: pypy/trunk/pypy/module/_winreg/ pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/ pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwinreg.py Log: Start a _winreg module Added: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 01:39:06 2009 @@ -0,0 +1,15 @@ +from pypy.interpreter.mixedmodule import MixedModule +from pypy.module._winreg import interp_winreg +from pypy.rlib.rwinreg import constants + +class Module(MixedModule): + appleveldefs = { + } + interpleveldefs = { + 'SetValue': 'interp_winreg.SetValue', + 'QueryValue': 'interp_winreg.QueryValue', + 'HKEYType': 'interp_winreg.W_HKEY', + } + + for name, value in constants.iteritems(): + interpleveldefs[name] = "space.wrap(%s)" % (value,) Added: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 01:39:06 2009 @@ -0,0 +1,86 @@ +from pypy.interpreter.baseobjspace import Wrappable +from pypy.interpreter.baseobjspace import ObjSpace, W_Root +from pypy.interpreter.gateway import interp2app +from pypy.interpreter.typedef import TypeDef +from pypy.interpreter.error import OperationError +from pypy.rpython.lltypesystem import rffi, lltype +from pypy.rlib import rwinreg, rwin32 + +class W_HKEY(Wrappable): + def __init__(self, hkey): + self.hkey = hkey + + def __nonzero__(self): + return self.hkey != 0 + + def descr_repr(self, space): + return space.wrap("" % (self.hkey,)) + descr_repr.unwrap_spec = ['self', ObjSpace] + +def new_HKEY(space, w_subtype, hkey): + return space.wrap(W_HKEY(hkey)) +descr_HKEY_new = interp2app(new_HKEY, + unwrap_spec=[ObjSpace, W_Root, int]) + +W_HKEY.typedef = TypeDef( + "_winreg.HKEYType", + __new__ = descr_HKEY_new, + __repr__ = interp2app(W_HKEY.descr_repr), + ) + +def hkey_w(w_key, space): + if space.is_w(w_key, space.w_None): + errstring = space.wrap("None is not a valid HKEY in this context") + raise OperationError(space.w_TypeError, errstring) + elif isinstance(w_key, W_HKEY): + return w_key.hkey + elif space.is_true(space.isinstance(w_key, space.w_int)): + return space.int_w(w_key) + elif space.is_true(space.isinstance(w_key, space.w_long)): + return space.uint_w(w_key) + else: + errstring = space.wrap("The object is not a PyHKEY object") + raise OperationError(space.w_TypeError, errstring) + +def SetValue(space, w_key, w_subkey, typ, value): + if typ != rwinreg.REG_SZ: + errstring = space.wrap("Type must be _winreg.REG_SZ") + raise OperationError(space.w_ValueError, errstring) + key = hkey_w(w_key, space) + if space.is_w(w_subkey, space.w_None): + subkey = None + else: + subkey = space.str_w(w_subkey) + dataptr = rffi.str2charp(value) + try: + ret = rwinreg.RegSetValue(key, subkey, rwinreg.REG_SZ, dataptr, len(value)) + finally: + rffi.free_charp(dataptr) + if ret != 0: + rwin32.raiseWindowError(ret, 'RegSetValue') +SetValue.unwrap_spec = [ObjSpace, W_Root, W_Root, int, str] + +def QueryValue(space, w_key, w_subkey): + key = hkey_w(w_key, space) + if space.is_w(w_subkey, space.w_None): + subkey = None + else: + subkey = space.str_w(w_subkey) + bufsize_p = lltype.malloc(rwin32.PLONG.TO, 1, flavor='raw') + try: + ret = rwinreg.RegQueryValue(key, subkey, None, bufsize_p) + if ret != 0: + rwin32.raiseWindowError(ret, 'RegQueryValue') + buf = lltype.malloc(rffi.CCHARP.TO, bufsize_p[0], flavor='raw') + try: + ret = rwinreg.RegQueryValue(key, subkey, buf, bufsize_p) + if ret != 0: + rwin32.raiseWindowError(ret, 'RegQueryValue') + return space.wrap(rffi.charp2strn(buf, bufsize_p[0] - 1)) + finally: + lltype.free(buf, flavor='raw') + finally: + lltype.free(bufsize_p, flavor='raw') + if ret != 0: + rwin32.raiseWindowError(ret, 'RegQueryValue') +SetValue.unwrap_spec = [ObjSpace, W_Root, W_Root, int, str] Added: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 01:39:06 2009 @@ -0,0 +1,40 @@ +from pypy.conftest import gettestobjspace + +import os, sys, py + +if sys.platform != 'win32': + py.test.skip("_winreg is a win32 module") + +class AppTestHKey: + def setup_class(cls): + space = gettestobjspace(usemodules=('_winreg',)) + cls.space = space + + def test_repr(self): + import _winreg + k = _winreg.HKEYType(123) + assert str(k) == "" + +class AppTestFfi: + def setup_class(cls): + import _winreg + space = gettestobjspace(usemodules=('_winreg',)) + cls.space = space + cls.root_key = _winreg.HKEY_CURRENT_USER + cls.test_key_name = "SOFTWARE\\Pypy Registry Test Key - Delete Me" + cls.w_root_key = space.wrap(cls.root_key) + cls.w_test_key_name = space.wrap(cls.test_key_name) + + def teardown_class(cls): + import _winreg + return + try: + _winreg.DeleteKey(cls.root_key, cls.test_key_name) + except WindowsError: + pass + + def test_simple_write(self): + from _winreg import SetValue, QueryValue, REG_SZ + value = "Some Default value" + SetValue(self.root_key, self.test_key_name, REG_SZ, value) + assert QueryValue(self.root_key, self.test_key_name) == value Added: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- (empty file) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 01:39:06 2009 @@ -0,0 +1,53 @@ +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.tool import rffi_platform as platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rlib import rwin32 + +eci = ExternalCompilationInfo( + includes = ['windows.h', + ], + libraries = ('Advapi32',) + ) +class CConfig: + _compilation_info_ = eci + + +constant_names = ''' +KEY_QUERY_VALUE KEY_SET_VALUE KEY_CREATE_SUB_KEY KEY_ENUMERATE_SUB_KEYS +KEY_NOTIFY KEY_CREATE_LINK KEY_READ KEY_WRITE KEY_EXECUTE KEY_ALL_ACCESS +KEY_WOW64_64KEY KEY_WOW64_32KEY REG_OPTION_RESERVED REG_OPTION_NON_VOLATILE +REG_OPTION_VOLATILE REG_OPTION_CREATE_LINK REG_OPTION_BACKUP_RESTORE +REG_OPTION_OPEN_LINK REG_LEGAL_OPTION REG_CREATED_NEW_KEY +REG_OPENED_EXISTING_KEY REG_WHOLE_HIVE_VOLATILE REG_REFRESH_HIVE +REG_NO_LAZY_FLUSH REG_NOTIFY_CHANGE_NAME REG_NOTIFY_CHANGE_ATTRIBUTES +REG_NOTIFY_CHANGE_LAST_SET REG_NOTIFY_CHANGE_SECURITY REG_LEGAL_CHANGE_FILTER +REG_NONE REG_SZ REG_EXPAND_SZ REG_BINARY REG_DWORD REG_DWORD_LITTLE_ENDIAN +REG_DWORD_BIG_ENDIAN REG_LINK REG_MULTI_SZ REG_RESOURCE_LIST +REG_FULL_RESOURCE_DESCRIPTOR REG_RESOURCE_REQUIREMENTS_LIST + +HKEY_LOCAL_MACHINE HKEY_CLASSES_ROOT HKEY_CURRENT_CONFIG HKEY_CURRENT_USER +HKEY_DYN_DATA HKEY_LOCAL_MACHINE HKEY_PERFORMANCE_DATATA HKEY_USERS +'''.split() +for name in constant_names: + setattr(CConfig, name, platform.DefinedConstantInteger(name)) + +constants = {} +cConfig = platform.configure(CConfig) +constants.update(cConfig) +globals().update(cConfig) + +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci, + calling_conv='win') + +HKEY = rwin32.HANDLE + +RegSetValue = external('RegSetValueA', + [HKEY, rffi.CCHARP, rwin32.DWORD, + rffi.CCHARP, rwin32.DWORD], + rffi.LONG) + +RegQueryValue = external('RegQueryValueA', + [HKEY, rffi.CCHARP, + rffi.CCHARP, rwin32.PLONG], + rffi.LONG) From pedronis at codespeak.net Thu Feb 19 13:41:24 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 19 Feb 2009 13:41:24 +0100 (CET) Subject: [pypy-svn] r62018 - pypy/trunk/pypy Message-ID: <20090219124124.24D2F168514@codespeak.net> Author: pedronis Date: Thu Feb 19 13:41:21 2009 New Revision: 62018 Modified: pypy/trunk/pypy/conftest.py Log: fixes the help and avoids the strange hack Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Thu Feb 19 13:41:21 2009 @@ -23,7 +23,6 @@ def _set_platform(opt, opt_str, value, parser): from pypy.config.translationoption import PLATFORMS from pypy.translator.platform import set_platform - value = parser.rargs.pop(0) if value not in PLATFORMS: raise ValueError("%s not in %s" % (value, PLATFORMS)) set_platform(value, None) @@ -37,7 +36,7 @@ Option('--direct', action="store_true", default=False, dest="rundirect", help="run pexpect tests directly"), - Option('-P', '--platform', action="callback", + Option('-P', '--platform', action="callback", type="string", default="host", callback=_set_platform, help="set up tests to use specified platform as compile/run target"), ) From afa at codespeak.net Thu Feb 19 15:55:17 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 15:55:17 +0100 (CET) Subject: [pypy-svn] r62020 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219145517.2EE49169E12@codespeak.net> Author: afa Date: Thu Feb 19 15:55:14 2009 New Revision: 62020 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwin32.py pypy/trunk/pypy/rlib/rwinreg.py Log: More progress on the winreg module Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 15:55:14 2009 @@ -6,9 +6,12 @@ appleveldefs = { } interpleveldefs = { + 'HKEYType': 'interp_winreg.W_HKEY', 'SetValue': 'interp_winreg.SetValue', 'QueryValue': 'interp_winreg.QueryValue', - 'HKEYType': 'interp_winreg.W_HKEY', + 'CreateKey': 'interp_winreg.CreateKey', + 'CloseKey': 'interp_winreg.CloseKey', + 'QueryInfoKey': 'interp_winreg.QueryInfoKey', } for name, value in constants.iteritems(): Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 15:55:14 2009 @@ -6,17 +6,30 @@ from pypy.rpython.lltypesystem import rffi, lltype from pypy.rlib import rwinreg, rwin32 +def raiseWindowsError(space, errcode, context): + message = rwin32.FormatError(errcode) + raise OperationError(space.w_WindowsError, space.wrap((errcode, message))) + class W_HKEY(Wrappable): def __init__(self, hkey): self.hkey = hkey - def __nonzero__(self): - return self.hkey != 0 + def descr_nonzero(self, space): + return self.wrap(self.hkey != 0) + descr_nonzero.unwrap_spec = ['self', ObjSpace] def descr_repr(self, space): - return space.wrap("" % (self.hkey,)) + return space.wrap("" % (self.hkey,)) descr_repr.unwrap_spec = ['self', ObjSpace] + def descr_int(self, space): + return space.wrap(self.hkey) + descr_int.unwrap_spec = ['self', ObjSpace] + + def Close(self, space): + CloseKey(space, self) + Close.unwrap_spec = ['self', ObjSpace] + def new_HKEY(space, w_subtype, hkey): return space.wrap(W_HKEY(hkey)) descr_HKEY_new = interp2app(new_HKEY, @@ -26,61 +39,111 @@ "_winreg.HKEYType", __new__ = descr_HKEY_new, __repr__ = interp2app(W_HKEY.descr_repr), + __int__ = interp2app(W_HKEY.descr_int), + __nonzero__ = interp2app(W_HKEY.descr_nonzero), + Close = interp2app(W_HKEY.Close), ) -def hkey_w(w_key, space): - if space.is_w(w_key, space.w_None): +def hkey_w(w_hkey, space): + if space.is_w(w_hkey, space.w_None): errstring = space.wrap("None is not a valid HKEY in this context") raise OperationError(space.w_TypeError, errstring) - elif isinstance(w_key, W_HKEY): - return w_key.hkey - elif space.is_true(space.isinstance(w_key, space.w_int)): - return space.int_w(w_key) - elif space.is_true(space.isinstance(w_key, space.w_long)): - return space.uint_w(w_key) + elif isinstance(w_hkey, W_HKEY): + return w_hkey.hkey + elif space.is_true(space.isinstance(w_hkey, space.w_int)): + return space.int_w(w_hkey) + elif space.is_true(space.isinstance(w_hkey, space.w_long)): + return space.uint_w(w_hkey) else: errstring = space.wrap("The object is not a PyHKEY object") raise OperationError(space.w_TypeError, errstring) -def SetValue(space, w_key, w_subkey, typ, value): +def CloseKey(space, w_hkey): + hkey = hkey_w(w_hkey, space) + if hkey: + ret = rwinreg.RegCloseKey(hkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegSetValue') +CloseKey.unwrap_spec = [ObjSpace, W_Root] + +def SetValue(space, w_hkey, w_subkey, typ, value): if typ != rwinreg.REG_SZ: errstring = space.wrap("Type must be _winreg.REG_SZ") raise OperationError(space.w_ValueError, errstring) - key = hkey_w(w_key, space) + hkey = hkey_w(w_hkey, space) if space.is_w(w_subkey, space.w_None): subkey = None else: subkey = space.str_w(w_subkey) dataptr = rffi.str2charp(value) try: - ret = rwinreg.RegSetValue(key, subkey, rwinreg.REG_SZ, dataptr, len(value)) + ret = rwinreg.RegSetValue(hkey, subkey, rwinreg.REG_SZ, dataptr, len(value)) finally: rffi.free_charp(dataptr) if ret != 0: - rwin32.raiseWindowError(ret, 'RegSetValue') + raiseWindowsError(space, ret, 'RegSetValue') SetValue.unwrap_spec = [ObjSpace, W_Root, W_Root, int, str] -def QueryValue(space, w_key, w_subkey): - key = hkey_w(w_key, space) +def QueryValue(space, w_hkey, w_subkey): + hkey = hkey_w(w_hkey, space) if space.is_w(w_subkey, space.w_None): subkey = None else: subkey = space.str_w(w_subkey) bufsize_p = lltype.malloc(rwin32.PLONG.TO, 1, flavor='raw') try: - ret = rwinreg.RegQueryValue(key, subkey, None, bufsize_p) + ret = rwinreg.RegQueryValue(hkey, subkey, None, bufsize_p) if ret != 0: - rwin32.raiseWindowError(ret, 'RegQueryValue') + raiseWindowsError(space, ret, 'RegQueryValue') buf = lltype.malloc(rffi.CCHARP.TO, bufsize_p[0], flavor='raw') try: - ret = rwinreg.RegQueryValue(key, subkey, buf, bufsize_p) + ret = rwinreg.RegQueryValue(hkey, subkey, buf, bufsize_p) if ret != 0: - rwin32.raiseWindowError(ret, 'RegQueryValue') + raiseWindowsError(space, ret, 'RegQueryValue') return space.wrap(rffi.charp2strn(buf, bufsize_p[0] - 1)) finally: lltype.free(buf, flavor='raw') finally: lltype.free(bufsize_p, flavor='raw') if ret != 0: - rwin32.raiseWindowError(ret, 'RegQueryValue') + raiseWindowsError(space, ret, 'RegQueryValue') SetValue.unwrap_spec = [ObjSpace, W_Root, W_Root, int, str] + +def CreateKey(space, w_hkey, subkey): + hkey = hkey_w(w_hkey, space) + rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') + try: + ret = rwinreg.RegCreateKey(hkey, subkey, rethkey) + if ret != 0: + raiseWindowsError(space, ret, 'CreateKey') + return space.wrap(W_HKEY(rethkey[0])) + finally: + lltype.free(rethkey, flavor='raw') +CreateKey.unwrap_spec = [ObjSpace, W_Root, str] + +def QueryInfoKey(space, w_hkey): + hkey = hkey_w(w_hkey, space) + nSubKeys = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') + try: + nValues = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') + try: + ft = lltype.malloc(rwin32.PFILETIME.TO, 1, flavor='raw') + try: + null_dword = lltype.nullptr(rwin32.LPDWORD.TO) + ret = rwinreg.RegQueryInfoKey( + hkey, None, null_dword, null_dword, + nSubKeys, null_dword, null_dword, + nValues, null_dword, null_dword, + null_dword, ft) + if ret != 0: + raiseWindowsError(space, ret, 'RegQueryInfoKey') + l = (ft[0].c_dwLowDateTime + + (ft[0].c_dwHighDateTime << 32)) + return space.wrap((nSubKeys[0], nValues[0], l)) + finally: + lltype.free(ft, flavor='raw') + finally: + lltype.free(nValues, flavor='raw') + finally: + lltype.free(nSubKeys, flavor='raw') +QueryInfoKey.unwrap_spec = [ObjSpace, W_Root] Modified: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/test/test_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 15:55:14 2009 @@ -12,8 +12,8 @@ def test_repr(self): import _winreg - k = _winreg.HKEYType(123) - assert str(k) == "" + k = _winreg.HKEYType(0x123) + assert str(k) == "" class AppTestFfi: def setup_class(cls): @@ -38,3 +38,34 @@ value = "Some Default value" SetValue(self.root_key, self.test_key_name, REG_SZ, value) assert QueryValue(self.root_key, self.test_key_name) == value + + def test_CreateKey(self): + from _winreg import CreateKey, CloseKey, QueryInfoKey + key = CreateKey(self.root_key, self.test_key_name) + sub_key = CreateKey(key, "sub_key") + + nkeys, nvalues, since_mod = QueryInfoKey(key) + assert nkeys == 1 + + nkeys, nvalues, since_mod = QueryInfoKey(sub_key) + assert nkeys == 0 + + int_sub_key = int(sub_key) + CloseKey(sub_key) + raises(EnvironmentError, QueryInfoKey, int_sub_key) + + int_key = int(key) + key.Close() + raises(EnvironmentError, QueryInfoKey, int_key) + + def test_exception(self): + from _winreg import QueryInfoKey + import errno + try: + QueryInfoKey(0) + except EnvironmentError, e: + assert e.winerror == 6 + assert e.errno == errno.EBADF + assert "invalid" in e.strerror.lower() + else: + assert 0, "Did not raise" Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Thu Feb 19 15:55:14 2009 @@ -39,6 +39,10 @@ HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG) HLOCAL = rffi_platform.SimpleType("HLOCAL", rffi.VOIDP) + FILETIME = rffi_platform.Struct('FILETIME', + [('dwLowDateTime', rffi.UINT), + ('dwHighDateTime', rffi.UINT)]) + DEFAULT_LANGUAGE = rffi_platform.ConstantInteger( "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)") @@ -57,6 +61,7 @@ HANDLE = rffi.ULONG LPHANDLE = rffi.CArrayPtr(HANDLE) HMODULE = HANDLE + PFILETIME = rffi.CArrayPtr(FILETIME) GetLastError = winexternal('GetLastError', [], DWORD) Modified: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- pypy/trunk/pypy/rlib/rwinreg.py (original) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 15:55:14 2009 @@ -41,13 +41,32 @@ calling_conv='win') HKEY = rwin32.HANDLE +PHKEY = rffi.CArrayPtr(HKEY) -RegSetValue = external('RegSetValueA', - [HKEY, rffi.CCHARP, rwin32.DWORD, - rffi.CCHARP, rwin32.DWORD], - rffi.LONG) - -RegQueryValue = external('RegQueryValueA', - [HKEY, rffi.CCHARP, - rffi.CCHARP, rwin32.PLONG], - rffi.LONG) +RegSetValue = external( + 'RegSetValueA', + [HKEY, rffi.CCHARP, rwin32.DWORD, rffi.CCHARP, rwin32.DWORD], + rffi.LONG) + +RegQueryValue = external( + 'RegQueryValueA', + [HKEY, rffi.CCHARP, rffi.CCHARP, rwin32.PLONG], + rffi.LONG) + +RegCreateKey = external( + 'RegCreateKeyA', + [rffi.LONG, rffi.CCHARP, PHKEY], + rffi.LONG) + +RegQueryInfoKey = external( + 'RegQueryInfoKeyA', + [HKEY, rffi.CCHARP, rwin32.LPDWORD, rwin32.LPDWORD, + rwin32.LPDWORD, rwin32.LPDWORD, rwin32.LPDWORD, + rwin32.LPDWORD, rwin32.LPDWORD, rwin32.LPDWORD, + rwin32.LPDWORD, rwin32.PFILETIME], + rffi.LONG) + +RegCloseKey = external( + 'RegCloseKey', + [HKEY], + rffi.LONG) From afa at codespeak.net Thu Feb 19 15:57:12 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 15:57:12 +0100 (CET) Subject: [pypy-svn] r62021 - pypy/trunk/pypy/module/_winreg Message-ID: <20090219145712.F0745169E2C@codespeak.net> Author: afa Date: Thu Feb 19 15:57:12 2009 New Revision: 62021 Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py Log: Fix the unwrap_spec Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 15:57:12 2009 @@ -107,7 +107,7 @@ lltype.free(bufsize_p, flavor='raw') if ret != 0: raiseWindowsError(space, ret, 'RegQueryValue') -SetValue.unwrap_spec = [ObjSpace, W_Root, W_Root, int, str] +QueryValue.unwrap_spec = [ObjSpace, W_Root, W_Root] def CreateKey(space, w_hkey, subkey): hkey = hkey_w(w_hkey, space) From afa at codespeak.net Thu Feb 19 17:22:03 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 17:22:03 +0100 (CET) Subject: [pypy-svn] r62022 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219162203.42B80169E6F@codespeak.net> Author: afa Date: Thu Feb 19 17:22:01 2009 New Revision: 62022 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwinreg.py Log: implement _winreg.RegSetValueEx Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 17:22:01 2009 @@ -8,6 +8,7 @@ interpleveldefs = { 'HKEYType': 'interp_winreg.W_HKEY', 'SetValue': 'interp_winreg.SetValue', + 'SetValueEx': 'interp_winreg.SetValueEx', 'QueryValue': 'interp_winreg.QueryValue', 'CreateKey': 'interp_winreg.CreateKey', 'CloseKey': 'interp_winreg.CloseKey', Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 17:22:01 2009 @@ -109,6 +109,88 @@ raiseWindowsError(space, ret, 'RegQueryValue') QueryValue.unwrap_spec = [ObjSpace, W_Root, W_Root] +def convert_to_regdata(space, w_value, typ): + buf = None + + if typ == rwinreg.REG_DWORD: + if space.is_true(space.isinstance(w_value, space.w_int)): + buflen = rffi.sizeof(rwin32.DWORD) + buf = lltype.malloc(rffi.CArray(rwin32.DWORD), 1, flavor='raw') + buf[0] = space.uint_w(w_value) + + elif typ == rwinreg.REG_SZ or typ == rwinreg.REG_EXPAND_SZ: + if space.is_w(w_value, space.w_None): + buflen = 1 + buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw') + buf[0] = 0 + else: + if space.is_true(space.isinstance(w_value, space.w_unicode)): + w_value = space.call_method(w_value, 'encode', + space.wrap('mbcs')) + buf = rffi.str2charp(space.str_w(w_value)) + buflen = space.int_w(space.len(w_value)) + 1 + + elif typ == rwinreg.REG_MULTI_SZ: + if space.is_w(w_value, space.w_None): + buflen = 1 + buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw') + buf[0] = 0 + elif space.is_true(space.isinstance(w_value, space.w_list)): + strings = [] + buflen = 0 + + # unwrap strings and compute total size + w_iter = space.iter(w_value) + while True: + try: + w_item = space.next(w_iter) + if space.is_true(space.isinstance(w_item, space.w_unicode)): + w_item = space.call_method(w_item, 'encode', + space.wrap('mbcs')) + item = space.str_w(w_item) + strings.append(item) + buflen += len(item) + 1 + except OperationError, e: + if not e.match(space, space.w_StopIteration): + raise # re-raise other app-level exceptions + break + buflen += 1 + buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw') + + # Now copy data + buflen = 0 + for string in strings: + for i in range(len(string)): + buf[buflen + i] = string[i] + buflen += len(string) + 1 + buf[buflen - 1] = '\0' + buflen += 1 + buf[buflen - 1] = '\0' + + else: # REG_BINARY and ALL unknown data types. + if space.is_w(w_value, space.w_None): + buflen = 0 + buf = lltype.malloc(rffi.CCHARP.TO, 1, flavor='raw') + else: + value = space.bufferstr_w(w_value) + buflen = len(value) + buf = rffi.str2charp(value) + + if buf is not None: + return rffi.cast(rffi.CCHARP, buf), buflen + + errstring = space.wrap("Could not convert the data to the specified type") + raise OperationError(space.w_ValueError, errstring) + +def SetValueEx(space, w_hkey, value_name, w_reserved, typ, w_value): + hkey = hkey_w(w_hkey, space) + buf, buflen = convert_to_regdata(space, w_value, typ) + try: + ret = rwinreg.RegSetValueEx(hkey, value_name, 0, typ, buf, buflen) + finally: + lltype.free(buf, flavor='raw') +SetValueEx.unwrap_spec = [ObjSpace, W_Root, str, W_Root, int, W_Root] + def CreateKey(space, w_hkey, subkey): hkey = hkey_w(w_hkey, space) rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') Modified: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/test/test_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 17:22:01 2009 @@ -27,7 +27,6 @@ def teardown_class(cls): import _winreg - return try: _winreg.DeleteKey(cls.root_key, cls.test_key_name) except WindowsError: @@ -69,3 +68,21 @@ assert "invalid" in e.strerror.lower() else: assert 0, "Did not raise" + + def test_SetValueEx(self): + from _winreg import CreateKey, SetValueEx + from _winreg import REG_DWORD, REG_SZ, REG_EXPAND_SZ + from _winreg import REG_MULTI_SZ, REG_BINARY + key = CreateKey(self.root_key, self.test_key_name) + SetValueEx(key, "Int Value", 0, + REG_DWORD, 45) + SetValueEx(key, "Str Value", 0, + REG_SZ, "A string Value") + SetValueEx(key, "Unicode Value", 0, + REG_SZ, u"A unicode Value") + SetValueEx(key, "Str Expand", 0, + REG_EXPAND_SZ, "The path is %path%") + SetValueEx(key, "Multi Str", 0, + REG_MULTI_SZ, ["Several", "string", u"values"]) + SetValueEx(key, "Raw data", 0, + REG_BINARY, "binary"+chr(0)+"data") Modified: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- pypy/trunk/pypy/rlib/rwinreg.py (original) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 17:22:01 2009 @@ -48,6 +48,12 @@ [HKEY, rffi.CCHARP, rwin32.DWORD, rffi.CCHARP, rwin32.DWORD], rffi.LONG) +RegSetValueEx = external( + 'RegSetValueExA', + [HKEY, rffi.CCHARP, rwin32.DWORD, + rwin32.DWORD, rffi.CCHARP, rwin32.DWORD], + rffi.LONG) + RegQueryValue = external( 'RegQueryValueA', [HKEY, rffi.CCHARP, rffi.CCHARP, rwin32.PLONG], From afa at codespeak.net Thu Feb 19 18:28:56 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 18:28:56 +0100 (CET) Subject: [pypy-svn] r62023 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219172856.88380169E83@codespeak.net> Author: afa Date: Thu Feb 19 18:28:54 2009 New Revision: 62023 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwinreg.py Log: winreg: add OpenKey and EnumValue Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 18:28:54 2009 @@ -11,6 +11,9 @@ 'SetValueEx': 'interp_winreg.SetValueEx', 'QueryValue': 'interp_winreg.QueryValue', 'CreateKey': 'interp_winreg.CreateKey', + 'OpenKey' : 'interp_winreg.OpenKey', + 'OpenKeyEx' : 'interp_winreg.OpenKey', + 'EnumValue' : 'interp_winreg.EnumValue', 'CloseKey': 'interp_winreg.CloseKey', 'QueryInfoKey': 'interp_winreg.QueryInfoKey', } Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 18:28:54 2009 @@ -182,6 +182,36 @@ errstring = space.wrap("Could not convert the data to the specified type") raise OperationError(space.w_ValueError, errstring) +def convert_from_regdata(space, buf, buflen, typ): + if typ == rwinreg.REG_DWORD: + if not buflen: + return 0 + return rffi.cast(rwin32.LPDWORD, buf)[0] + + elif typ == rwinreg.REG_SZ or typ == rwinreg.REG_EXPAND_SZ: + if not buflen: + return u"" + return rffi.charp2strn(rffi.cast(rffi.CCHARP, buf), buflen) + + elif typ == rwinreg.REG_MULTI_SZ: + if not buflen: + return [] + i = 0 + l = [] + while i < buflen and buf[i]: + s = [] + while i < buflen and buf[i] != '\0': + s.append(buf[i]) + i += 1 + if len(s) == 0: + break + l.append(''.join(s)) + i += 1 + return l + + else: # REG_BINARY and all other types + return rffi.charpsize2str(buf, buflen) + def SetValueEx(space, w_hkey, value_name, w_reserved, typ, w_value): hkey = hkey_w(w_hkey, space) buf, buflen = convert_to_regdata(space, w_value, typ) @@ -189,6 +219,8 @@ ret = rwinreg.RegSetValueEx(hkey, value_name, 0, typ, buf, buflen) finally: lltype.free(buf, flavor='raw') + if ret != 0: + raiseWindowsError(space, ret, 'RegSetValueEx') SetValueEx.unwrap_spec = [ObjSpace, W_Root, str, W_Root, int, W_Root] def CreateKey(space, w_hkey, subkey): @@ -203,6 +235,70 @@ lltype.free(rethkey, flavor='raw') CreateKey.unwrap_spec = [ObjSpace, W_Root, str] +def OpenKey(space, w_hkey, subkey, res=0, sam=rwinreg.KEY_READ): + hkey = hkey_w(w_hkey, space) + rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') + try: + ret = rwinreg.RegOpenKeyEx(hkey, subkey, res, sam, rethkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegOpenKeyEx') + return space.wrap(W_HKEY(rethkey[0])) + finally: + lltype.free(rethkey, flavor='raw') +OpenKey.unwrap_spec = [ObjSpace, W_Root, str, int, rffi.r_uint] + +def EnumValue(space, w_hkey, index): + hkey = hkey_w(w_hkey, space) + null_dword = lltype.nullptr(rwin32.LPDWORD.TO) + + retValueSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') + try: + retDataSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') + try: + ret = rwinreg.RegQueryInfoKey( + hkey, None, null_dword, null_dword, + null_dword, null_dword, null_dword, + null_dword, retValueSize, retDataSize, + null_dword, lltype.nullptr(rwin32.PFILETIME.TO)) + if ret != 0: + raiseWindowsError(space, ret, 'RegQueryInfoKey') + # include null terminators + retValueSize[0] += 1 + retDataSize[0] += 1 + + valuebuf = lltype.malloc(rffi.CCHARP.TO, retValueSize[0], + flavor='raw') + try: + databuf = lltype.malloc(rffi.CCHARP.TO, retDataSize[0], + flavor='raw') + try: + retType = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') + try: + ret = rwinreg.RegEnumValue( + hkey, index, valuebuf, retValueSize, + null_dword, retType, databuf, retDataSize) + if ret != 0: + raiseWindowsError(space, ret, 'RegEnumValue') + + return space.wrap(( + rffi.charp2str(valuebuf), + convert_from_regdata(space, databuf, + retDataSize[0], retType[0]), + retType[0] + )) + finally: + lltype.free(retType, flavor='raw') + finally: + lltype.free(databuf, flavor='raw') + finally: + lltype.free(valuebuf, flavor='raw') + finally: + lltype.free(retDataSize, flavor='raw') + finally: + lltype.free(retValueSize, flavor='raw') + +EnumValue.unwrap_spec = [ObjSpace, W_Root, int] + def QueryInfoKey(space, w_hkey): hkey = hkey_w(w_hkey, space) nSubKeys = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') Modified: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/test/test_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 18:28:54 2009 @@ -25,6 +25,16 @@ cls.w_root_key = space.wrap(cls.root_key) cls.w_test_key_name = space.wrap(cls.test_key_name) + test_data = [ + ("Int Value", 45, _winreg.REG_DWORD), + ("Str Value", "A string Value", _winreg.REG_SZ), + ("Unicode Value", u"A unicode Value", _winreg.REG_SZ), + ("Str Expand", "The path is %path%", _winreg.REG_EXPAND_SZ), + ("Multi Str", ["Several", "string", u"values"], _winreg.REG_MULTI_SZ), + ("Raw data", "binary"+chr(0)+"data", _winreg.REG_BINARY), + ] + cls.w_test_data = space.wrap(test_data) + def teardown_class(cls): import _winreg try: @@ -71,18 +81,21 @@ def test_SetValueEx(self): from _winreg import CreateKey, SetValueEx - from _winreg import REG_DWORD, REG_SZ, REG_EXPAND_SZ - from _winreg import REG_MULTI_SZ, REG_BINARY key = CreateKey(self.root_key, self.test_key_name) - SetValueEx(key, "Int Value", 0, - REG_DWORD, 45) - SetValueEx(key, "Str Value", 0, - REG_SZ, "A string Value") - SetValueEx(key, "Unicode Value", 0, - REG_SZ, u"A unicode Value") - SetValueEx(key, "Str Expand", 0, - REG_EXPAND_SZ, "The path is %path%") - SetValueEx(key, "Multi Str", 0, - REG_MULTI_SZ, ["Several", "string", u"values"]) - SetValueEx(key, "Raw data", 0, - REG_BINARY, "binary"+chr(0)+"data") + sub_key = CreateKey(key, "sub_key") + for name, value, type in self.test_data: + SetValueEx(sub_key, name, 0, type, value) + + def test_readValues(self): + from _winreg import OpenKey, EnumValue + key = OpenKey(self.root_key, self.test_key_name) + sub_key = OpenKey(key, "sub_key") + index = 0 + while 1: + try: + data = EnumValue(sub_key, index) + except EnvironmentError, e: + break + assert data in self.test_data + index = index + 1 + assert index == len(self.test_data) Modified: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- pypy/trunk/pypy/rlib/rwinreg.py (original) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 18:28:54 2009 @@ -42,6 +42,7 @@ HKEY = rwin32.HANDLE PHKEY = rffi.CArrayPtr(HKEY) +REGSAM = rwin32.DWORD RegSetValue = external( 'RegSetValueA', @@ -61,7 +62,19 @@ RegCreateKey = external( 'RegCreateKeyA', - [rffi.LONG, rffi.CCHARP, PHKEY], + [HKEY, rffi.CCHARP, PHKEY], + rffi.LONG) + +RegOpenKeyEx = external( + 'RegOpenKeyExA', + [HKEY, rffi.CCHARP, rwin32.DWORD, REGSAM, PHKEY], + rffi.LONG) + +RegEnumValue = external( + 'RegEnumValueA', + [HKEY, rwin32.DWORD, rffi.CCHARP, + rwin32.LPDWORD, rwin32.LPDWORD, rwin32.LPDWORD, + rffi.CCHARP, rwin32.LPDWORD], rffi.LONG) RegQueryInfoKey = external( From afa at codespeak.net Thu Feb 19 18:46:21 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 18:46:21 +0100 (CET) Subject: [pypy-svn] r62024 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219174621.D1498169E8E@codespeak.net> Author: afa Date: Thu Feb 19 18:46:19 2009 New Revision: 62024 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwinreg.py Log: _winreg.QueryValueEx Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 18:46:19 2009 @@ -10,6 +10,7 @@ 'SetValue': 'interp_winreg.SetValue', 'SetValueEx': 'interp_winreg.SetValueEx', 'QueryValue': 'interp_winreg.QueryValue', + 'QueryValueEx' : 'interp_winreg.QueryValueEx', 'CreateKey': 'interp_winreg.CreateKey', 'OpenKey' : 'interp_winreg.OpenKey', 'OpenKeyEx' : 'interp_winreg.OpenKey', Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 18:46:19 2009 @@ -223,6 +223,39 @@ raiseWindowsError(space, ret, 'RegSetValueEx') SetValueEx.unwrap_spec = [ObjSpace, W_Root, str, W_Root, int, W_Root] +def QueryValueEx(space, w_hkey, subkey): + hkey = hkey_w(w_hkey, space) + null_dword = lltype.nullptr(rwin32.LPDWORD.TO) + retDataSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') + try: + ret = rwinreg.RegQueryValueEx(hkey, subkey, null_dword, null_dword, + None, retDataSize) + if ret != 0: + print "AFA??", hkey, subkey + raiseWindowsError(space, ret, 'RegQueryValueEx') + databuf = lltype.malloc(rffi.CCHARP.TO, retDataSize[0], flavor='raw') + try: + retType = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') + try: + + ret = rwinreg.RegQueryValueEx(hkey, subkey, null_dword, + retType, databuf, retDataSize) + if ret != 0: + raiseWindowsError(space, ret, 'RegQueryValueEx') + return space.wrap(( + convert_from_regdata(space, databuf, + retDataSize[0], retType[0]), + retType[0], + )) + finally: + lltype.free(retType, flavor='raw') + finally: + lltype.free(databuf, flavor='raw') + finally: + lltype.free(retDataSize, flavor='raw') + +QueryValueEx.unwrap_spec = [ObjSpace, W_Root, str] + def CreateKey(space, w_hkey, subkey): hkey = hkey_w(w_hkey, space) rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') @@ -284,7 +317,7 @@ rffi.charp2str(valuebuf), convert_from_regdata(space, databuf, retDataSize[0], retType[0]), - retType[0] + retType[0], )) finally: lltype.free(retType, flavor='raw') Modified: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/test/test_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 18:46:19 2009 @@ -87,7 +87,7 @@ SetValueEx(sub_key, name, 0, type, value) def test_readValues(self): - from _winreg import OpenKey, EnumValue + from _winreg import OpenKey, EnumValue, QueryValueEx key = OpenKey(self.root_key, self.test_key_name) sub_key = OpenKey(key, "sub_key") index = 0 @@ -99,3 +99,6 @@ assert data in self.test_data index = index + 1 assert index == len(self.test_data) + + for name, data, type in self.test_data: + assert QueryValueEx(sub_key, name) == (data, type) Modified: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- pypy/trunk/pypy/rlib/rwinreg.py (original) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 18:46:19 2009 @@ -60,6 +60,12 @@ [HKEY, rffi.CCHARP, rffi.CCHARP, rwin32.PLONG], rffi.LONG) +RegQueryValueEx = external( + 'RegQueryValueExA', + [HKEY, rffi.CCHARP, rwin32.LPDWORD, rwin32.LPDWORD, + rffi.CCHARP, rwin32.LPDWORD], + rffi.LONG) + RegCreateKey = external( 'RegCreateKeyA', [HKEY, rffi.CCHARP, PHKEY], From afa at codespeak.net Thu Feb 19 18:59:08 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 18:59:08 +0100 (CET) Subject: [pypy-svn] r62025 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219175908.2F05C169E78@codespeak.net> Author: afa Date: Thu Feb 19 18:59:05 2009 New Revision: 62025 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwinreg.py Log: implement winreg.EnumKey Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 18:59:05 2009 @@ -15,6 +15,7 @@ 'OpenKey' : 'interp_winreg.OpenKey', 'OpenKeyEx' : 'interp_winreg.OpenKey', 'EnumValue' : 'interp_winreg.EnumValue', + 'EnumKey' : 'interp_winreg.EnumKey', 'CloseKey': 'interp_winreg.CloseKey', 'QueryInfoKey': 'interp_winreg.QueryInfoKey', } Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 18:59:05 2009 @@ -332,6 +332,29 @@ EnumValue.unwrap_spec = [ObjSpace, W_Root, int] +def EnumKey(space, w_hkey, index): + hkey = hkey_w(w_hkey, space) + null_dword = lltype.nullptr(rwin32.LPDWORD.TO) + + # max key name length is 255 + buf = lltype.malloc(rffi.CCHARP.TO, 256, flavor='raw') + try: + retValueSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') + try: + retValueSize[0] = 256 # includes NULL terminator + ret = rwinreg.RegEnumKeyEx(hkey, index, buf, retValueSize, + null_dword, None, null_dword, + lltype.nullptr(rwin32.PFILETIME.TO)) + if ret != 0: + raiseWindowsError(space, ret, 'RegEnumKeyEx') + return space.wrap(rffi.charp2str(buf)) + finally: + lltype.free(retValueSize, flavor='raw') + finally: + lltype.free(buf, flavor='raw') + +EnumKey.unwrap_spec = [ObjSpace, W_Root, int] + def QueryInfoKey(space, w_hkey): hkey = hkey_w(w_hkey, space) nSubKeys = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') Modified: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/test/test_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 18:59:05 2009 @@ -87,7 +87,7 @@ SetValueEx(sub_key, name, 0, type, value) def test_readValues(self): - from _winreg import OpenKey, EnumValue, QueryValueEx + from _winreg import OpenKey, EnumValue, QueryValueEx, EnumKey key = OpenKey(self.root_key, self.test_key_name) sub_key = OpenKey(key, "sub_key") index = 0 @@ -102,3 +102,6 @@ for name, data, type in self.test_data: assert QueryValueEx(sub_key, name) == (data, type) + + assert EnumKey(key, 0) == "sub_key" + raises(EnvironmentError, EnumKey, key, 1) Modified: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- pypy/trunk/pypy/rlib/rwinreg.py (original) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 18:59:05 2009 @@ -83,6 +83,13 @@ rffi.CCHARP, rwin32.LPDWORD], rffi.LONG) +RegEnumKeyEx = external( + 'RegEnumKeyExA', + [HKEY, rwin32.DWORD, rffi.CCHARP, + rwin32.LPDWORD, rwin32.LPDWORD, + rffi.CCHARP, rwin32.LPDWORD, rwin32.PFILETIME], + rffi.LONG) + RegQueryInfoKey = external( 'RegQueryInfoKeyA', [HKEY, rffi.CCHARP, rwin32.LPDWORD, rwin32.LPDWORD, From afa at codespeak.net Thu Feb 19 20:02:48 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 20:02:48 +0100 (CET) Subject: [pypy-svn] r62026 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219190248.2B2C7169E7C@codespeak.net> Author: afa Date: Thu Feb 19 20:02:45 2009 New Revision: 62026 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwinreg.py Log: winreg: add DeleteValue and DeleteKey Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 20:02:45 2009 @@ -12,6 +12,8 @@ 'QueryValue': 'interp_winreg.QueryValue', 'QueryValueEx' : 'interp_winreg.QueryValueEx', 'CreateKey': 'interp_winreg.CreateKey', + 'DeleteKey' : 'interp_winreg.DeleteKey', + 'DeleteValue' : 'interp_winreg.DeleteValue', 'OpenKey' : 'interp_winreg.OpenKey', 'OpenKeyEx' : 'interp_winreg.OpenKey', 'EnumValue' : 'interp_winreg.EnumValue', Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 20:02:45 2009 @@ -14,6 +14,10 @@ def __init__(self, hkey): self.hkey = hkey + def descr_del(self, space): + self.Close(space) + descr_del.unwrap_spec = ['self', ObjSpace] + def descr_nonzero(self, space): return self.wrap(self.hkey != 0) descr_nonzero.unwrap_spec = ['self', ObjSpace] @@ -38,6 +42,7 @@ W_HKEY.typedef = TypeDef( "_winreg.HKEYType", __new__ = descr_HKEY_new, + __del__ = interp2app(W_HKEY.descr_del), __repr__ = interp2app(W_HKEY.descr_repr), __int__ = interp2app(W_HKEY.descr_int), __nonzero__ = interp2app(W_HKEY.descr_nonzero), @@ -231,7 +236,6 @@ ret = rwinreg.RegQueryValueEx(hkey, subkey, null_dword, null_dword, None, retDataSize) if ret != 0: - print "AFA??", hkey, subkey raiseWindowsError(space, ret, 'RegQueryValueEx') databuf = lltype.malloc(rffi.CCHARP.TO, retDataSize[0], flavor='raw') try: @@ -268,6 +272,20 @@ lltype.free(rethkey, flavor='raw') CreateKey.unwrap_spec = [ObjSpace, W_Root, str] +def DeleteKey(space, w_hkey, subkey): + hkey = hkey_w(w_hkey, space) + ret = rwinreg.RegDeleteKey(hkey, subkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegDeleteKey') +DeleteKey.unwrap_spec = [ObjSpace, W_Root, str] + +def DeleteValue(space, w_hkey, subkey): + hkey = hkey_w(w_hkey, space) + ret = rwinreg.RegDeleteValue(hkey, subkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegDeleteValue') +DeleteValue.unwrap_spec = [ObjSpace, W_Root, str] + def OpenKey(space, w_hkey, subkey, res=0, sam=rwinreg.KEY_READ): hkey = hkey_w(w_hkey, space) rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') Modified: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/test/test_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 20:02:45 2009 @@ -100,8 +100,18 @@ index = index + 1 assert index == len(self.test_data) - for name, data, type in self.test_data: - assert QueryValueEx(sub_key, name) == (data, type) + for name, value, type in self.test_data: + assert QueryValueEx(sub_key, name) == (value, type) assert EnumKey(key, 0) == "sub_key" raises(EnvironmentError, EnumKey, key, 1) + + def test_delete(self): + from _winreg import OpenKey, KEY_ALL_ACCESS, DeleteValue, DeleteKey + key = OpenKey(self.root_key, self.test_key_name, 0, KEY_ALL_ACCESS) + sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS) + + for name, value, type in self.test_data: + DeleteValue(sub_key, name) + + DeleteKey(key, "sub_key") Modified: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- pypy/trunk/pypy/rlib/rwinreg.py (original) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 20:02:45 2009 @@ -71,6 +71,16 @@ [HKEY, rffi.CCHARP, PHKEY], rffi.LONG) +RegDeleteValue = external( + 'RegDeleteValueA', + [HKEY, rffi.CCHARP], + rffi.LONG) + +RegDeleteKey = external( + 'RegDeleteKeyA', + [HKEY, rffi.CCHARP], + rffi.LONG) + RegOpenKeyEx = external( 'RegOpenKeyExA', [HKEY, rffi.CCHARP, rwin32.DWORD, REGSAM, PHKEY], From afa at codespeak.net Thu Feb 19 20:17:29 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 20:17:29 +0100 (CET) Subject: [pypy-svn] r62027 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219191729.76DE7169E85@codespeak.net> Author: afa Date: Thu Feb 19 20:17:28 2009 New Revision: 62027 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwinreg.py Log: Add winreg.ConnectRegistry. All of CPython's test_winreg test suite passes... on top of py.py Now let's see if it translates... Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 20:17:28 2009 @@ -20,6 +20,7 @@ 'EnumKey' : 'interp_winreg.EnumKey', 'CloseKey': 'interp_winreg.CloseKey', 'QueryInfoKey': 'interp_winreg.QueryInfoKey', + 'ConnectRegistry': 'interp_winreg.ConnectRegistry', } for name, value in constants.iteritems(): Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 20:17:28 2009 @@ -399,3 +399,21 @@ finally: lltype.free(nSubKeys, flavor='raw') QueryInfoKey.unwrap_spec = [ObjSpace, W_Root] + +def str_or_None_w(space, w_obj): + if space.is_w(w_obj, space.w_None): + return None + return space.str_w(w_obj) + +def ConnectRegistry(space, w_machine, w_hkey): + machine = str_or_None_w(space, w_machine) + hkey = hkey_w(w_hkey, space) + rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') + try: + ret = rwinreg.RegConnectRegistry(machine, hkey, rethkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegConnectRegistry') + return space.wrap(W_HKEY(rethkey[0])) + finally: + lltype.free(rethkey, flavor='raw') +ConnectRegistry.unwrap_spec = [ObjSpace, W_Root, W_Root] Modified: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/test/test_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 20:17:28 2009 @@ -115,3 +115,8 @@ DeleteValue(sub_key, name) DeleteKey(key, "sub_key") + + def test_connect(self): + from _winreg import ConnectRegistry, HKEY_LOCAL_MACHINE + h = ConnectRegistry(None, HKEY_LOCAL_MACHINE) + h.Close() Modified: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- pypy/trunk/pypy/rlib/rwinreg.py (original) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 20:17:28 2009 @@ -112,3 +112,8 @@ 'RegCloseKey', [HKEY], rffi.LONG) + +RegConnectRegistry = external( + 'RegConnectRegistryA', + [rffi.CCHARP, HKEY, PHKEY], + rffi.LONG) From afa at codespeak.net Thu Feb 19 20:38:35 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 20:38:35 +0100 (CET) Subject: [pypy-svn] r62028 - pypy/trunk/pypy/module/_winreg Message-ID: <20090219193835.61462169E7E@codespeak.net> Author: afa Date: Thu Feb 19 20:38:34 2009 New Revision: 62028 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py Log: winreg: add docstrings, and some translation fixes Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 20:38:34 2009 @@ -3,6 +3,42 @@ from pypy.rlib.rwinreg import constants class Module(MixedModule): + """This module provides access to the Windows registry API. + +Functions: + +CloseKey() - Closes a registry key. +ConnectRegistry() - Establishes a connection to a predefined registry handle + on another computer. +CreateKey() - Creates the specified key, or opens it if it already exists. +DeleteKey() - Deletes the specified key. +DeleteValue() - Removes a named value from the specified registry key. +EnumKey() - Enumerates subkeys of the specified open registry key. +EnumValue() - Enumerates values of the specified open registry key. +ExpandEnvironmentStrings() - Expand the env strings in a REG_EXPAND_SZ string. +FlushKey() - Writes all the attributes of the specified key to the registry. +LoadKey() - Creates a subkey under HKEY_USER or HKEY_LOCAL_MACHINE and stores + registration information from a specified file into that subkey. +OpenKey() - Alias for +OpenKeyEx() - Opens the specified key. +QueryValue() - Retrieves the value associated with the unnamed value for a + specified key in the registry. +QueryValueEx() - Retrieves the type and data for a specified value name + associated with an open registry key. +QueryInfoKey() - Returns information about the specified key. +SaveKey() - Saves the specified key, and all its subkeys a file. +SetValue() - Associates a value with a specified key. +SetValueEx() - Stores data in the value field of an open registry key. + +Special objects: + +HKEYType -- type object for HKEY objects +error -- exception raised for Win32 errors + +Integer constants: +Many constants are defined - see the documentation for each function +to see what constants are used, and where.""" + appleveldefs = { } interpleveldefs = { Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 20:38:34 2009 @@ -31,6 +31,8 @@ descr_int.unwrap_spec = ['self', ObjSpace] def Close(self, space): + """key.Close() - Closes the underlying Windows handle. +If the handle is already closed, no error is raised.""" CloseKey(space, self) Close.unwrap_spec = ['self', ObjSpace] @@ -41,6 +43,27 @@ W_HKEY.typedef = TypeDef( "_winreg.HKEYType", + __doc__ = """\ +PyHKEY Object - A Python object, representing a win32 registry key. + +This object wraps a Windows HKEY object, automatically closing it when +the object is destroyed. To guarantee cleanup, you can call either +the Close() method on the PyHKEY, or the CloseKey() method. + +All functions which accept a handle object also accept an integer - +however, use of the handle object is encouraged. + +Functions: +Close() - Closes the underlying handle. +Detach() - Returns the integer Win32 handle, detaching it from the object + +Properties: +handle - The integer Win32 handle. + +Operations: +__nonzero__ - Handles with an open object return true, otherwise false. +__int__ - Converting a handle to an integer returns the Win32 handle. +__cmp__ - Handle objects are compared using the handle value.""", __new__ = descr_HKEY_new, __del__ = interp2app(W_HKEY.descr_del), __repr__ = interp2app(W_HKEY.descr_repr), @@ -64,6 +87,12 @@ raise OperationError(space.w_TypeError, errstring) def CloseKey(space, w_hkey): + """CloseKey(hkey) - Closes a previously opened registry key. + +The hkey argument specifies a previously opened key. + +Note that if the key is not closed using this method, it will be +closed when the hkey object is destroyed by Python.""" hkey = hkey_w(w_hkey, space) if hkey: ret = rwinreg.RegCloseKey(hkey) @@ -72,6 +101,23 @@ CloseKey.unwrap_spec = [ObjSpace, W_Root] def SetValue(space, w_hkey, w_subkey, typ, value): + """SetValue(key, sub_key, type, value) - Associates a value with a specified key. + +key is an already open key, or any one of the predefined HKEY_* constants. +sub_key is a string that names the subkey with which the value is associated. +type is an integer that specifies the type of the data. Currently this + must be REG_SZ, meaning only strings are supported. +value is a string that specifies the new value. + +If the key specified by the sub_key parameter does not exist, the SetValue +function creates it. + +Value lengths are limited by available memory. Long values (more than +2048 bytes) should be stored as files with the filenames stored in +the configuration registry. This helps the registry perform efficiently. + +The key identified by the key parameter must have been opened with +KEY_SET_VALUE access.""" if typ != rwinreg.REG_SZ: errstring = space.wrap("Type must be _winreg.REG_SZ") raise OperationError(space.w_ValueError, errstring) @@ -90,6 +136,16 @@ SetValue.unwrap_spec = [ObjSpace, W_Root, W_Root, int, str] def QueryValue(space, w_hkey, w_subkey): + """string = QueryValue(key, sub_key) - retrieves the unnamed value for a key. + +key is an already open key, or any one of the predefined HKEY_* constants. +sub_key is a string that holds the name of the subkey with which the value + is associated. If this parameter is None or empty, the function retrieves + the value set by the SetValue() method for the key identified by key. + +Values in the registry have name, type, and data components. This method +retrieves the data for a key's first value that has a NULL name. +But the underlying API call doesn't return the type, Lame Lame Lame, DONT USE THIS!!!""" hkey = hkey_w(w_hkey, space) if space.is_w(w_subkey, space.w_None): subkey = None @@ -120,14 +176,15 @@ if typ == rwinreg.REG_DWORD: if space.is_true(space.isinstance(w_value, space.w_int)): buflen = rffi.sizeof(rwin32.DWORD) - buf = lltype.malloc(rffi.CArray(rwin32.DWORD), 1, flavor='raw') - buf[0] = space.uint_w(w_value) + buf1 = lltype.malloc(rffi.CArray(rwin32.DWORD), 1, flavor='raw') + buf1[0] = space.uint_w(w_value) + buf = rffi.cast(rffi.CCHARP, buf1) elif typ == rwinreg.REG_SZ or typ == rwinreg.REG_EXPAND_SZ: if space.is_w(w_value, space.w_None): buflen = 1 buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw') - buf[0] = 0 + buf[0] = '\0' else: if space.is_true(space.isinstance(w_value, space.w_unicode)): w_value = space.call_method(w_value, 'encode', @@ -139,7 +196,7 @@ if space.is_w(w_value, space.w_None): buflen = 1 buf = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw') - buf[0] = 0 + buf[0] = '\0' elif space.is_true(space.isinstance(w_value, space.w_list)): strings = [] buflen = 0 @@ -176,6 +233,7 @@ if space.is_w(w_value, space.w_None): buflen = 0 buf = lltype.malloc(rffi.CCHARP.TO, 1, flavor='raw') + buf[0] = '\0' else: value = space.bufferstr_w(w_value) buflen = len(value) @@ -218,6 +276,36 @@ return rffi.charpsize2str(buf, buflen) def SetValueEx(space, w_hkey, value_name, w_reserved, typ, w_value): + """SetValueEx(key, value_name, reserved, type, value) - Stores data in the value field of an open registry key. + +key is an already open key, or any one of the predefined HKEY_* constants. +value_name is a string containing the name of the value to set, or None +type is an integer that specifies the type of the data. This should be one of: + REG_BINARY -- Binary data in any form. + REG_DWORD -- A 32-bit number. + REG_DWORD_LITTLE_ENDIAN -- A 32-bit number in little-endian format. + REG_DWORD_BIG_ENDIAN -- A 32-bit number in big-endian format. + REG_EXPAND_SZ -- A null-terminated string that contains unexpanded references + to environment variables (for example, %PATH%). + REG_LINK -- A Unicode symbolic link. + REG_MULTI_SZ -- An sequence of null-terminated strings, terminated by + two null characters. Note that Python handles this + termination automatically. + REG_NONE -- No defined value type. + REG_RESOURCE_LIST -- A device-driver resource list. + REG_SZ -- A null-terminated string. +reserved can be anything - zero is always passed to the API. +value is a string that specifies the new value. + +This method can also set additional value and type information for the +specified key. The key identified by the key parameter must have been +opened with KEY_SET_VALUE access. + +To open the key, use the CreateKeyEx() or OpenKeyEx() methods. + +Value lengths are limited by available memory. Long values (more than +2048 bytes) should be stored as files with the filenames stored in +the configuration registry. This helps the registry perform efficiently.""" hkey = hkey_w(w_hkey, space) buf, buflen = convert_to_regdata(space, w_value, typ) try: @@ -229,6 +317,10 @@ SetValueEx.unwrap_spec = [ObjSpace, W_Root, str, W_Root, int, W_Root] def QueryValueEx(space, w_hkey, subkey): + """value,type_id = QueryValueEx(key, value_name) - Retrieves the type and data for a specified value name associated with an open registry key. + +key is an already open key, or any one of the predefined HKEY_* constants. +value_name is a string indicating the value to query""" hkey = hkey_w(w_hkey, space) null_dword = lltype.nullptr(rwin32.LPDWORD.TO) retDataSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') @@ -261,6 +353,17 @@ QueryValueEx.unwrap_spec = [ObjSpace, W_Root, str] def CreateKey(space, w_hkey, subkey): + """key = CreateKey(key, sub_key) - Creates or opens the specified key. + +key is an already open key, or one of the predefined HKEY_* constants +sub_key is a string that names the key this method opens or creates. + If key is one of the predefined keys, sub_key may be None. In that case, + the handle returned is the same key handle passed in to the function. + +If the key already exists, this function opens the existing key + +The return value is the handle of the opened key. +If the function fails, an exception is raised.""" hkey = hkey_w(w_hkey, space) rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') try: @@ -273,6 +376,16 @@ CreateKey.unwrap_spec = [ObjSpace, W_Root, str] def DeleteKey(space, w_hkey, subkey): + """DeleteKey(key, sub_key) - Deletes the specified key. + +key is an already open key, or any one of the predefined HKEY_* constants. +sub_key is a string that must be a subkey of the key identified by the key parameter. + This value must not be None, and the key may not have subkeys. + +This method can not delete keys with subkeys. + +If the method succeeds, the entire key, including all of its values, +is removed. If the method fails, an EnvironmentError exception is raised.""" hkey = hkey_w(w_hkey, space) ret = rwinreg.RegDeleteKey(hkey, subkey) if ret != 0: @@ -280,6 +393,10 @@ DeleteKey.unwrap_spec = [ObjSpace, W_Root, str] def DeleteValue(space, w_hkey, subkey): + """DeleteValue(key, value) - Removes a named value from a registry key. + +key is an already open key, or any one of the predefined HKEY_* constants. +value is a string that identifies the value to remove.""" hkey = hkey_w(w_hkey, space) ret = rwinreg.RegDeleteValue(hkey, subkey) if ret != 0: @@ -287,6 +404,16 @@ DeleteValue.unwrap_spec = [ObjSpace, W_Root, str] def OpenKey(space, w_hkey, subkey, res=0, sam=rwinreg.KEY_READ): + """key = OpenKey(key, sub_key, res = 0, sam = KEY_READ) - Opens the specified key. + +key is an already open key, or any one of the predefined HKEY_* constants. +sub_key is a string that identifies the sub_key to open +res is a reserved integer, and must be zero. Default is zero. +sam is an integer that specifies an access mask that describes the desired + security access for the key. Default is KEY_READ + +The result is a new handle to the specified key +If the function fails, an EnvironmentError exception is raised.""" hkey = hkey_w(w_hkey, space) rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') try: @@ -299,6 +426,19 @@ OpenKey.unwrap_spec = [ObjSpace, W_Root, str, int, rffi.r_uint] def EnumValue(space, w_hkey, index): + """tuple = EnumValue(key, index) - Enumerates values of an open registry key. +key is an already open key, or any one of the predefined HKEY_* constants. +index is an integer that identifies the index of the value to retrieve. + +The function retrieves the name of one subkey each time it is called. +It is typically called repeatedly, until an EnvironmentError exception +is raised, indicating no more values. + +The result is a tuple of 3 items: +value_name is a string that identifies the value. +value_data is an object that holds the value data, and whose type depends + on the underlying registry type. +data_type is an integer that identifies the type of the value data.""" hkey = hkey_w(w_hkey, space) null_dword = lltype.nullptr(rwin32.LPDWORD.TO) @@ -351,6 +491,14 @@ EnumValue.unwrap_spec = [ObjSpace, W_Root, int] def EnumKey(space, w_hkey, index): + """string = EnumKey(key, index) - Enumerates subkeys of an open registry key. + +key is an already open key, or any one of the predefined HKEY_* constants. +index is an integer that identifies the index of the key to retrieve. + +The function retrieves the name of one subkey each time it is called. +It is typically called repeatedly until an EnvironmentError exception is +raised, indicating no more values are available.""" hkey = hkey_w(w_hkey, space) null_dword = lltype.nullptr(rwin32.LPDWORD.TO) @@ -374,6 +522,15 @@ EnumKey.unwrap_spec = [ObjSpace, W_Root, int] def QueryInfoKey(space, w_hkey): + """tuple = QueryInfoKey(key) - Returns information about a key. + +key is an already open key, or any one of the predefined HKEY_* constants. + +The result is a tuple of 3 items: +An integer that identifies the number of sub keys this key has. +An integer that identifies the number of values this key has. +A long integer that identifies when the key was last modified (if available) + as 100's of nanoseconds since Jan 1, 1600.""" hkey = hkey_w(w_hkey, space) nSubKeys = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor='raw') try: @@ -406,6 +563,16 @@ return space.str_w(w_obj) def ConnectRegistry(space, w_machine, w_hkey): + """key = ConnectRegistry(computer_name, key) + +Establishes a connection to a predefined registry handle on another computer. + +computer_name is the name of the remote computer, of the form \\\\computername. + If None, the local computer is used. +key is the predefined handle to connect to. + +The return value is the handle of the opened key. +If the function fails, an EnvironmentError exception is raised.""" machine = str_or_None_w(space, w_machine) hkey = hkey_w(w_hkey, space) rethkey = lltype.malloc(rwinreg.PHKEY.TO, 1, flavor='raw') @@ -417,3 +584,78 @@ finally: lltype.free(rethkey, flavor='raw') ConnectRegistry.unwrap_spec = [ObjSpace, W_Root, W_Root] + +## XXX missing functions + +## "string = ExpandEnvironmentStrings(string) - Expand environment vars.\n"); + +## "FlushKey(key) - Writes all the attributes of a key to the registry.\n" +## "\n" +## "key is an already open key, or any one of the predefined HKEY_* constants.\n" +## "\n" +## "It is not necessary to call RegFlushKey to change a key.\n" +## "Registry changes are flushed to disk by the registry using its lazy flusher.\n" +## "Registry changes are also flushed to disk at system shutdown.\n" +## "Unlike CloseKey(), the FlushKey() method returns only when all the data has\n" +## "been written to the registry.\n" +## "An application should only call FlushKey() if it requires absolute certainty that registry changes are on disk.\n" +## "If you don't know whether a FlushKey() call is required, it probably isn't."); + +## "LoadKey(key, sub_key, file_name) - Creates a subkey under the specified key\n" +## "and stores registration information from a specified file into that subkey.\n" +## "\n" +## "key is an already open key, or any one of the predefined HKEY_* constants.\n" +## "sub_key is a string that identifies the sub_key to load\n" +## "file_name is the name of the file to load registry data from.\n" +## " This file must have been created with the SaveKey() function.\n" +## " Under the file allocation table (FAT) file system, the filename may not\n" +## "have an extension.\n" +## "\n" +## "A call to LoadKey() fails if the calling process does not have the\n" +## "SE_RESTORE_PRIVILEGE privilege.\n" +## "\n" +## "If key is a handle returned by ConnectRegistry(), then the path specified\n" +## "in fileName is relative to the remote computer.\n" +## "\n" +## "The docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE tree"); + +## "SaveKey(key, file_name) - Saves the specified key, and all its subkeys to the specified file.\n" +## "\n" +## "key is an already open key, or any one of the predefined HKEY_* constants.\n" +## "file_name is the name of the file to save registry data to.\n" +## " This file cannot already exist. If this filename includes an extension,\n" +## " it cannot be used on file allocation table (FAT) file systems by the\n" +## " LoadKey(), ReplaceKey() or RestoreKey() methods.\n" +## "\n" +## "If key represents a key on a remote computer, the path described by\n" +## "file_name is relative to the remote computer.\n" +## "The caller of this method must possess the SeBackupPrivilege security privilege.\n" +## "This function passes NULL for security_attributes to the API."); + +## PyDoc_STRVAR(DisableReflectionKey_doc, +## "Disables registry reflection for 32-bit processes running on a 64-bit\n" +## "Operating System. Will generally raise NotImplemented if executed on\n" +## "a 32-bit Operating System.\n" +## "If the key is not on the reflection list, the function succeeds but has no effect.\n" +## "Disabling reflection for a key does not affect reflection of any subkeys."); + +## PyDoc_STRVAR(EnableReflectionKey_doc, +## "Restores registry reflection for the specified disabled key.\n" +## "Will generally raise NotImplemented if executed on a 32-bit Operating System.\n" +## "Restoring reflection for a key does not affect reflection of any subkeys."); + +## PyDoc_STRVAR(QueryReflectionKey_doc, +## "bool = QueryReflectionKey(hkey) - Determines the reflection state for the specified key.\n" +## "Will generally raise NotImplemented if executed on a 32-bit Operating System.\n"); + +## PyDoc_STRVAR(PyHKEY_Detach_doc, +## "int = key.Detach() - Detaches the Windows handle from the handle object.\n" +## "\n" +## "The result is the value of the handle before it is detached. If the\n" +## "handle is already detached, this will return zero.\n" +## "\n" +## "After calling this function, the handle is effectively invalidated,\n" +## "but the handle is not closed. You would call this function when you\n" +## "need the underlying win32 handle to exist beyond the lifetime of the\n" +## "handle object.\n" +## "On 64 bit windows, the result of this function is a long integer"); From afa at codespeak.net Thu Feb 19 20:39:21 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 20:39:21 +0100 (CET) Subject: [pypy-svn] r62029 - pypy/trunk/pypy/module/_winreg Message-ID: <20090219193921.86654169E8E@codespeak.net> Author: afa Date: Thu Feb 19 20:39:21 2009 New Revision: 62029 Modified: pypy/trunk/pypy/module/_winreg/__init__.py Log: line up declarations Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 20:39:21 2009 @@ -42,20 +42,20 @@ appleveldefs = { } interpleveldefs = { - 'HKEYType': 'interp_winreg.W_HKEY', - 'SetValue': 'interp_winreg.SetValue', - 'SetValueEx': 'interp_winreg.SetValueEx', - 'QueryValue': 'interp_winreg.QueryValue', - 'QueryValueEx' : 'interp_winreg.QueryValueEx', - 'CreateKey': 'interp_winreg.CreateKey', - 'DeleteKey' : 'interp_winreg.DeleteKey', - 'DeleteValue' : 'interp_winreg.DeleteValue', - 'OpenKey' : 'interp_winreg.OpenKey', - 'OpenKeyEx' : 'interp_winreg.OpenKey', - 'EnumValue' : 'interp_winreg.EnumValue', - 'EnumKey' : 'interp_winreg.EnumKey', - 'CloseKey': 'interp_winreg.CloseKey', - 'QueryInfoKey': 'interp_winreg.QueryInfoKey', + 'HKEYType' : 'interp_winreg.W_HKEY', + 'SetValue' : 'interp_winreg.SetValue', + 'SetValueEx' : 'interp_winreg.SetValueEx', + 'QueryValue' : 'interp_winreg.QueryValue', + 'QueryValueEx' : 'interp_winreg.QueryValueEx', + 'CreateKey' : 'interp_winreg.CreateKey', + 'DeleteKey' : 'interp_winreg.DeleteKey', + 'DeleteValue' : 'interp_winreg.DeleteValue', + 'OpenKey' : 'interp_winreg.OpenKey', + 'OpenKeyEx' : 'interp_winreg.OpenKey', + 'EnumValue' : 'interp_winreg.EnumValue', + 'EnumKey' : 'interp_winreg.EnumKey', + 'CloseKey' : 'interp_winreg.CloseKey', + 'QueryInfoKey' : 'interp_winreg.QueryInfoKey', 'ConnectRegistry': 'interp_winreg.ConnectRegistry', } From afa at codespeak.net Thu Feb 19 23:21:42 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 19 Feb 2009 23:21:42 +0100 (CET) Subject: [pypy-svn] r62034 - in pypy/trunk/pypy: module/_winreg module/_winreg/test rlib Message-ID: <20090219222142.5C155169E98@codespeak.net> Author: afa Date: Thu Feb 19 23:21:40 2009 New Revision: 62034 Modified: pypy/trunk/pypy/module/_winreg/__init__.py pypy/trunk/pypy/module/_winreg/interp_winreg.py pypy/trunk/pypy/module/_winreg/test/test_winreg.py pypy/trunk/pypy/rlib/rwin32.py pypy/trunk/pypy/rlib/rwinreg.py Log: Add the missing functions to _winreg, not tested by CPython test suite. Modified: pypy/trunk/pypy/module/_winreg/__init__.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/__init__.py (original) +++ pypy/trunk/pypy/module/_winreg/__init__.py Thu Feb 19 23:21:40 2009 @@ -54,8 +54,11 @@ 'OpenKeyEx' : 'interp_winreg.OpenKey', 'EnumValue' : 'interp_winreg.EnumValue', 'EnumKey' : 'interp_winreg.EnumKey', + 'FlushKey' : 'interp_winreg.FlushKey', 'CloseKey' : 'interp_winreg.CloseKey', 'QueryInfoKey' : 'interp_winreg.QueryInfoKey', + 'LoadKey' : 'interp_winreg.LoadKey', + 'SaveKey' : 'interp_winreg.SaveKey', 'ConnectRegistry': 'interp_winreg.ConnectRegistry', } Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Thu Feb 19 23:21:40 2009 @@ -36,6 +36,22 @@ CloseKey(space, self) Close.unwrap_spec = ['self', ObjSpace] + def Detach(self, space): + """int = key.Detach() - Detaches the Windows handle from the handle object. + +The result is the value of the handle before it is detached. If the +handle is already detached, this will return zero. + +After calling this function, the handle is effectively invalidated, +but the handle is not closed. You would call this function when you +need the underlying win32 handle to exist beyond the lifetime of the +handle object. +On 64 bit windows, the result of this function is a long integer""" + hkey = self.hkey + self.hkey = 0 + return space.wrap(hkey) + Detach.unwrap_spec = ['self', ObjSpace] + def new_HKEY(space, w_subtype, hkey): return space.wrap(W_HKEY(hkey)) descr_HKEY_new = interp2app(new_HKEY, @@ -70,6 +86,7 @@ __int__ = interp2app(W_HKEY.descr_int), __nonzero__ = interp2app(W_HKEY.descr_nonzero), Close = interp2app(W_HKEY.Close), + Detach = interp2app(W_HKEY.Detach), ) def hkey_w(w_hkey, space): @@ -97,9 +114,72 @@ if hkey: ret = rwinreg.RegCloseKey(hkey) if ret != 0: - raiseWindowsError(space, ret, 'RegSetValue') + raiseWindowsError(space, ret, 'RegCloseKey') CloseKey.unwrap_spec = [ObjSpace, W_Root] +def FlushKey(space, w_hkey): + """FlushKey(key) - Writes all the attributes of a key to the registry. + +key is an already open key, or any one of the predefined HKEY_* constants. + +It is not necessary to call RegFlushKey to change a key. +Registry changes are flushed to disk by the registry using its lazy flusher. +Registry changes are also flushed to disk at system shutdown. +Unlike CloseKey(), the FlushKey() method returns only when all the data has +been written to the registry. +An application should only call FlushKey() if it requires absolute certainty that registry changes are on disk. +If you don't know whether a FlushKey() call is required, it probably isn't.""" + hkey = hkey_w(w_hkey, space) + if hkey: + ret = rwinreg.RegFlushKey(hkey) + if ret != 0: + raiseWindowsError(space, ret, 'RegFlushKey') +FlushKey.unwrap_spec = [ObjSpace, W_Root] + +def LoadKey(space, w_hkey, subkey, filename): + """LoadKey(key, sub_key, file_name) - Creates a subkey under the specified key +and stores registration information from a specified file into that subkey. + +key is an already open key, or any one of the predefined HKEY_* constants. +sub_key is a string that identifies the sub_key to load +file_name is the name of the file to load registry data from. + This file must have been created with the SaveKey() function. + Under the file allocation table (FAT) file system, the filename may not +have an extension. + +A call to LoadKey() fails if the calling process does not have the +SE_RESTORE_PRIVILEGE privilege. + +If key is a handle returned by ConnectRegistry(), then the path specified +in fileName is relative to the remote computer. + +The docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE tree""" + hkey = hkey_w(w_hkey, space) + ret = rwinreg.RegLoadKey(hkey, subkey, filename) + if ret != 0: + raiseWindowsError(space, ret, 'RegLoadKey') +LoadKey.unwrap_spec = [ObjSpace, W_Root, str, str] + +def SaveKey(space, w_hkey, filename): + """SaveKey(key, file_name) - Saves the specified key, and all its subkeys to the specified file. + +key is an already open key, or any one of the predefined HKEY_* constants. +file_name is the name of the file to save registry data to. + This file cannot already exist. If this filename includes an extension, + it cannot be used on file allocation table (FAT) file systems by the + LoadKey(), ReplaceKey() or RestoreKey() methods. + +If key represents a key on a remote computer, the path described by +file_name is relative to the remote computer. +The caller of this method must possess the SeBackupPrivilege security privilege. +This function passes NULL for security_attributes to the API.""" + hkey = hkey_w(w_hkey, space) + pSA = 0 + ret = rwinreg.RegSaveKey(hkey, filename, None) + if ret != 0: + raiseWindowsError(space, ret, 'RegSaveKey') +SaveKey.unwrap_spec = [ObjSpace, W_Root, str] + def SetValue(space, w_hkey, w_subkey, typ, value): """SetValue(key, sub_key, type, value) - Associates a value with a specified key. @@ -584,78 +664,3 @@ finally: lltype.free(rethkey, flavor='raw') ConnectRegistry.unwrap_spec = [ObjSpace, W_Root, W_Root] - -## XXX missing functions - -## "string = ExpandEnvironmentStrings(string) - Expand environment vars.\n"); - -## "FlushKey(key) - Writes all the attributes of a key to the registry.\n" -## "\n" -## "key is an already open key, or any one of the predefined HKEY_* constants.\n" -## "\n" -## "It is not necessary to call RegFlushKey to change a key.\n" -## "Registry changes are flushed to disk by the registry using its lazy flusher.\n" -## "Registry changes are also flushed to disk at system shutdown.\n" -## "Unlike CloseKey(), the FlushKey() method returns only when all the data has\n" -## "been written to the registry.\n" -## "An application should only call FlushKey() if it requires absolute certainty that registry changes are on disk.\n" -## "If you don't know whether a FlushKey() call is required, it probably isn't."); - -## "LoadKey(key, sub_key, file_name) - Creates a subkey under the specified key\n" -## "and stores registration information from a specified file into that subkey.\n" -## "\n" -## "key is an already open key, or any one of the predefined HKEY_* constants.\n" -## "sub_key is a string that identifies the sub_key to load\n" -## "file_name is the name of the file to load registry data from.\n" -## " This file must have been created with the SaveKey() function.\n" -## " Under the file allocation table (FAT) file system, the filename may not\n" -## "have an extension.\n" -## "\n" -## "A call to LoadKey() fails if the calling process does not have the\n" -## "SE_RESTORE_PRIVILEGE privilege.\n" -## "\n" -## "If key is a handle returned by ConnectRegistry(), then the path specified\n" -## "in fileName is relative to the remote computer.\n" -## "\n" -## "The docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE tree"); - -## "SaveKey(key, file_name) - Saves the specified key, and all its subkeys to the specified file.\n" -## "\n" -## "key is an already open key, or any one of the predefined HKEY_* constants.\n" -## "file_name is the name of the file to save registry data to.\n" -## " This file cannot already exist. If this filename includes an extension,\n" -## " it cannot be used on file allocation table (FAT) file systems by the\n" -## " LoadKey(), ReplaceKey() or RestoreKey() methods.\n" -## "\n" -## "If key represents a key on a remote computer, the path described by\n" -## "file_name is relative to the remote computer.\n" -## "The caller of this method must possess the SeBackupPrivilege security privilege.\n" -## "This function passes NULL for security_attributes to the API."); - -## PyDoc_STRVAR(DisableReflectionKey_doc, -## "Disables registry reflection for 32-bit processes running on a 64-bit\n" -## "Operating System. Will generally raise NotImplemented if executed on\n" -## "a 32-bit Operating System.\n" -## "If the key is not on the reflection list, the function succeeds but has no effect.\n" -## "Disabling reflection for a key does not affect reflection of any subkeys."); - -## PyDoc_STRVAR(EnableReflectionKey_doc, -## "Restores registry reflection for the specified disabled key.\n" -## "Will generally raise NotImplemented if executed on a 32-bit Operating System.\n" -## "Restoring reflection for a key does not affect reflection of any subkeys."); - -## PyDoc_STRVAR(QueryReflectionKey_doc, -## "bool = QueryReflectionKey(hkey) - Determines the reflection state for the specified key.\n" -## "Will generally raise NotImplemented if executed on a 32-bit Operating System.\n"); - -## PyDoc_STRVAR(PyHKEY_Detach_doc, -## "int = key.Detach() - Detaches the Windows handle from the handle object.\n" -## "\n" -## "The result is the value of the handle before it is detached. If the\n" -## "handle is already detached, this will return zero.\n" -## "\n" -## "After calling this function, the handle is effectively invalidated,\n" -## "but the handle is not closed. You would call this function when you\n" -## "need the underlying win32 handle to exist beyond the lifetime of the\n" -## "handle object.\n" -## "On 64 bit windows, the result of this function is a long integer"); Modified: pypy/trunk/pypy/module/_winreg/test/test_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/test/test_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/test/test_winreg.py Thu Feb 19 23:21:40 2009 @@ -1,10 +1,24 @@ from pypy.conftest import gettestobjspace +from pypy.tool.udir import udir import os, sys, py if sys.platform != 'win32': py.test.skip("_winreg is a win32 module") +try: + # To call SaveKey, the process must have Backup Privileges + import win32api + import win32security + priv_flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY + hToken = win32security.OpenProcessToken (win32api.GetCurrentProcess (), priv_flags) + privilege_id = win32security.LookupPrivilegeValue (None, "SeBackupPrivilege") + win32security.AdjustTokenPrivileges (hToken, 0, [(privilege_id, win32security.SE_PRIVILEGE_ENABLED)]) +except: + canSaveKey = False +else: + canSaveKey = True + class AppTestHKey: def setup_class(cls): space = gettestobjspace(usemodules=('_winreg',)) @@ -24,6 +38,8 @@ cls.test_key_name = "SOFTWARE\\Pypy Registry Test Key - Delete Me" cls.w_root_key = space.wrap(cls.root_key) cls.w_test_key_name = space.wrap(cls.test_key_name) + cls.w_canSaveKey = space.wrap(canSaveKey) + cls.w_tmpfilename = space.wrap(str(udir.join('winreg-temp'))) test_data = [ ("Int Value", 45, _winreg.REG_DWORD), @@ -49,7 +65,7 @@ assert QueryValue(self.root_key, self.test_key_name) == value def test_CreateKey(self): - from _winreg import CreateKey, CloseKey, QueryInfoKey + from _winreg import CreateKey, QueryInfoKey key = CreateKey(self.root_key, self.test_key_name) sub_key = CreateKey(key, "sub_key") @@ -59,7 +75,13 @@ nkeys, nvalues, since_mod = QueryInfoKey(sub_key) assert nkeys == 0 + def test_close(self): + from _winreg import OpenKey, CloseKey, FlushKey, QueryInfoKey + key = OpenKey(self.root_key, self.test_key_name) + sub_key = OpenKey(key, "sub_key") + int_sub_key = int(sub_key) + FlushKey(sub_key) CloseKey(sub_key) raises(EnvironmentError, QueryInfoKey, int_sub_key) @@ -67,6 +89,14 @@ key.Close() raises(EnvironmentError, QueryInfoKey, int_key) + key = OpenKey(self.root_key, self.test_key_name) + int_key = key.Detach() + QueryInfoKey(int_key) # works + key.Close() + QueryInfoKey(int_key) # still works + CloseKey(int_key) + raises(EnvironmentError, QueryInfoKey, int_key) # now closed + def test_exception(self): from _winreg import QueryInfoKey import errno @@ -75,7 +105,9 @@ except EnvironmentError, e: assert e.winerror == 6 assert e.errno == errno.EBADF - assert "invalid" in e.strerror.lower() + # XXX translations... + assert ("invalid" in e.strerror.lower() or + "non valide" in e.strerror.lower()) else: assert 0, "Did not raise" @@ -120,3 +152,16 @@ from _winreg import ConnectRegistry, HKEY_LOCAL_MACHINE h = ConnectRegistry(None, HKEY_LOCAL_MACHINE) h.Close() + + def test_savekey(self): + if not self.canSaveKey: + skip("CPython needs win32api to set the SeBackupPrivilege security privilege") + from _winreg import OpenKey, KEY_ALL_ACCESS, SaveKey + import os + try: + os.unlink(self.tmpfilename) + except: + pass + + key = OpenKey(self.root_key, self.test_key_name, 0, KEY_ALL_ACCESS) + SaveKey(key, self.tmpfilename) Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Thu Feb 19 23:21:40 2009 @@ -43,13 +43,16 @@ [('dwLowDateTime', rffi.UINT), ('dwHighDateTime', rffi.UINT)]) + LPSECURITY_ATTRIBUTES = rffi_platform.SimpleType( + "LPSECURITY_ATTRIBUTES", rffi.CCHARP) + DEFAULT_LANGUAGE = rffi_platform.ConstantInteger( "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)") for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM """.split(): locals()[name] = rffi_platform.ConstantInteger(name) - + for k, v in rffi_platform.configure(CConfig).items(): globals()[k] = v Modified: pypy/trunk/pypy/rlib/rwinreg.py ============================================================================== --- pypy/trunk/pypy/rlib/rwinreg.py (original) +++ pypy/trunk/pypy/rlib/rwinreg.py Thu Feb 19 23:21:40 2009 @@ -113,6 +113,21 @@ [HKEY], rffi.LONG) +RegFlushKey = external( + 'RegFlushKey', + [HKEY], + rffi.LONG) + +RegLoadKey = external( + 'RegLoadKeyA', + [HKEY, rffi.CCHARP, rffi.CCHARP], + rffi.LONG) + +RegSaveKey = external( + 'RegSaveKeyA', + [HKEY, rffi.CCHARP, rffi.VOIDP], + rffi.LONG) + RegConnectRegistry = external( 'RegConnectRegistryA', [rffi.CCHARP, HKEY, PHKEY], From afa at codespeak.net Fri Feb 20 00:29:02 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 00:29:02 +0100 (CET) Subject: [pypy-svn] r62036 - pypy/trunk/pypy/module/_winreg Message-ID: <20090219232902.4C60F169E99@codespeak.net> Author: afa Date: Fri Feb 20 00:29:01 2009 New Revision: 62036 Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py Log: "space.wrap(tuple) forbidden; use newtuple()" Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Fri Feb 20 00:29:01 2009 @@ -8,7 +8,8 @@ def raiseWindowsError(space, errcode, context): message = rwin32.FormatError(errcode) - raise OperationError(space.w_WindowsError, space.wrap((errcode, message))) + raise OperationError(space.w_WindowsError, + space.newtuple([errcode, message])) class W_HKEY(Wrappable): def __init__(self, hkey): @@ -418,11 +419,11 @@ retType, databuf, retDataSize) if ret != 0: raiseWindowsError(space, ret, 'RegQueryValueEx') - return space.wrap(( + return space.newtuple([ convert_from_regdata(space, databuf, retDataSize[0], retType[0]), retType[0], - )) + ]) finally: lltype.free(retType, flavor='raw') finally: @@ -551,12 +552,12 @@ if ret != 0: raiseWindowsError(space, ret, 'RegEnumValue') - return space.wrap(( + return space.newtuple([ rffi.charp2str(valuebuf), convert_from_regdata(space, databuf, retDataSize[0], retType[0]), retType[0], - )) + ]) finally: lltype.free(retType, flavor='raw') finally: @@ -628,7 +629,7 @@ raiseWindowsError(space, ret, 'RegQueryInfoKey') l = (ft[0].c_dwLowDateTime + (ft[0].c_dwHighDateTime << 32)) - return space.wrap((nSubKeys[0], nValues[0], l)) + return space.newtuple([nSubKeys[0], nValues[0], l]) finally: lltype.free(ft, flavor='raw') finally: From afa at codespeak.net Fri Feb 20 00:47:05 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 00:47:05 +0100 (CET) Subject: [pypy-svn] r62037 - pypy/trunk/pypy/module/_winreg Message-ID: <20090219234705.909FF169EA5@codespeak.net> Author: afa Date: Fri Feb 20 00:47:02 2009 New Revision: 62037 Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py Log: space.newtuple wants wrapped items Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Fri Feb 20 00:47:02 2009 @@ -9,7 +9,8 @@ def raiseWindowsError(space, errcode, context): message = rwin32.FormatError(errcode) raise OperationError(space.w_WindowsError, - space.newtuple([errcode, message])) + space.newtuple([space.wrap(errcode), + space.wrap(message)])) class W_HKEY(Wrappable): def __init__(self, hkey): @@ -326,7 +327,7 @@ errstring = space.wrap("Could not convert the data to the specified type") raise OperationError(space.w_ValueError, errstring) -def convert_from_regdata(space, buf, buflen, typ): +def convert_from_regdata(buf, buflen, typ): if typ == rwinreg.REG_DWORD: if not buflen: return 0 @@ -420,9 +421,10 @@ if ret != 0: raiseWindowsError(space, ret, 'RegQueryValueEx') return space.newtuple([ - convert_from_regdata(space, databuf, - retDataSize[0], retType[0]), - retType[0], + space.wrap(convert_from_regdata(databuf, + retDataSize[0], + retType[0])), + space.wrap(retType[0]), ]) finally: lltype.free(retType, flavor='raw') @@ -553,10 +555,11 @@ raiseWindowsError(space, ret, 'RegEnumValue') return space.newtuple([ - rffi.charp2str(valuebuf), - convert_from_regdata(space, databuf, - retDataSize[0], retType[0]), - retType[0], + space.wrap(rffi.charp2str(valuebuf)), + space.wrap(convert_from_regdata(databuf, + retDataSize[0], + retType[0])), + space.wrap(retType[0]), ]) finally: lltype.free(retType, flavor='raw') @@ -629,7 +632,9 @@ raiseWindowsError(space, ret, 'RegQueryInfoKey') l = (ft[0].c_dwLowDateTime + (ft[0].c_dwHighDateTime << 32)) - return space.newtuple([nSubKeys[0], nValues[0], l]) + return space.newtuple([space.wrap(nSubKeys[0]), + space.wrap(nValues[0]), + space.wrap(l)]) finally: lltype.free(ft, flavor='raw') finally: From afa at codespeak.net Fri Feb 20 01:01:53 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 01:01:53 +0100 (CET) Subject: [pypy-svn] r62038 - pypy/trunk/pypy/module/_winreg Message-ID: <20090220000153.C8F6A169EA5@codespeak.net> Author: afa Date: Fri Feb 20 01:01:49 2009 New Revision: 62038 Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py Log: fix annotation by returning a wrapped object in every case Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Fri Feb 20 01:01:49 2009 @@ -327,20 +327,22 @@ errstring = space.wrap("Could not convert the data to the specified type") raise OperationError(space.w_ValueError, errstring) -def convert_from_regdata(buf, buflen, typ): +def convert_from_regdata(space, buf, buflen, typ): if typ == rwinreg.REG_DWORD: if not buflen: - return 0 - return rffi.cast(rwin32.LPDWORD, buf)[0] + return space.wrap(0) + d = rffi.cast(rwin32.LPDWORD, buf)[0] + return space.wrap(d) elif typ == rwinreg.REG_SZ or typ == rwinreg.REG_EXPAND_SZ: if not buflen: - return u"" - return rffi.charp2strn(rffi.cast(rffi.CCHARP, buf), buflen) + return space.wrap("") + s = rffi.charp2strn(rffi.cast(rffi.CCHARP, buf), buflen) + return space.wrap(s) elif typ == rwinreg.REG_MULTI_SZ: if not buflen: - return [] + return space.wrap([]) i = 0 l = [] while i < buflen and buf[i]: @@ -352,10 +354,10 @@ break l.append(''.join(s)) i += 1 - return l + return space.wrap(l) else: # REG_BINARY and all other types - return rffi.charpsize2str(buf, buflen) + return space.wrap(rffi.charpsize2str(buf, buflen)) def SetValueEx(space, w_hkey, value_name, w_reserved, typ, w_value): """SetValueEx(key, value_name, reserved, type, value) - Stores data in the value field of an open registry key. @@ -421,9 +423,8 @@ if ret != 0: raiseWindowsError(space, ret, 'RegQueryValueEx') return space.newtuple([ - space.wrap(convert_from_regdata(databuf, - retDataSize[0], - retType[0])), + convert_from_regdata(space, databuf, + retDataSize[0], retType[0]), space.wrap(retType[0]), ]) finally: @@ -556,9 +557,8 @@ return space.newtuple([ space.wrap(rffi.charp2str(valuebuf)), - space.wrap(convert_from_regdata(databuf, - retDataSize[0], - retType[0])), + convert_from_regdata(space, databuf, + retDataSize[0], retType[0]), space.wrap(retType[0]), ]) finally: From afa at codespeak.net Fri Feb 20 01:15:29 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 01:15:29 +0100 (CET) Subject: [pypy-svn] r62039 - pypy/trunk/pypy/module/_winreg Message-ID: <20090220001529.5B492169E9D@codespeak.net> Author: afa Date: Fri Feb 20 01:15:28 2009 New Revision: 62039 Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py Log: Use space.newlist to create a wrapped list Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Fri Feb 20 01:15:28 2009 @@ -342,7 +342,7 @@ elif typ == rwinreg.REG_MULTI_SZ: if not buflen: - return space.wrap([]) + return space.newlist([]) i = 0 l = [] while i < buflen and buf[i]: @@ -352,9 +352,10 @@ i += 1 if len(s) == 0: break - l.append(''.join(s)) + s = ''.join(s) + l.append(space.wrap(s)) i += 1 - return space.wrap(l) + return space.newlist(l) else: # REG_BINARY and all other types return space.wrap(rffi.charpsize2str(buf, buflen)) From afa at codespeak.net Fri Feb 20 01:29:08 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 01:29:08 +0100 (CET) Subject: [pypy-svn] r62040 - pypy/trunk/pypy/module/_winreg Message-ID: <20090220002908.E554E169E98@codespeak.net> Author: afa Date: Fri Feb 20 01:29:08 2009 New Revision: 62040 Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py Log: translation fix Modified: pypy/trunk/pypy/module/_winreg/interp_winreg.py ============================================================================== --- pypy/trunk/pypy/module/_winreg/interp_winreg.py (original) +++ pypy/trunk/pypy/module/_winreg/interp_winreg.py Fri Feb 20 01:29:08 2009 @@ -21,7 +21,7 @@ descr_del.unwrap_spec = ['self', ObjSpace] def descr_nonzero(self, space): - return self.wrap(self.hkey != 0) + return space.wrap(self.hkey != 0) descr_nonzero.unwrap_spec = ['self', ObjSpace] def descr_repr(self, space): From afa at codespeak.net Fri Feb 20 10:41:27 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 10:41:27 +0100 (CET) Subject: [pypy-svn] r62044 - in pypy/trunk: lib-python pypy/config pypy/doc/config Message-ID: <20090220094127.A10D6169E86@codespeak.net> Author: afa Date: Fri Feb 20 10:41:24 2009 New Revision: 62044 Added: pypy/trunk/pypy/doc/config/objspace.usemodules._winreg.txt Modified: pypy/trunk/lib-python/conftest.py pypy/trunk/pypy/config/pypyoption.py Log: On Windows, _winreg is now a Working Module. Modified: pypy/trunk/lib-python/conftest.py ============================================================================== --- pypy/trunk/lib-python/conftest.py (original) +++ pypy/trunk/lib-python/conftest.py Fri Feb 20 10:41:24 2009 @@ -437,7 +437,7 @@ RegrTest('test_weakref.py', core=True, usemodules='_weakref'), RegrTest('test_whichdb.py'), - RegrTest('test_winreg.py', skip="unsupported extension module"), + RegrTest('test_winreg.py', skip=sys.platform != 'win32'), RegrTest('test_winsound.py', skip="unsupported extension module"), RegrTest('test_xmllib.py'), RegrTest('test_xmlrpc.py'), Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Fri Feb 20 10:41:24 2009 @@ -39,6 +39,7 @@ # XXX this should move somewhere else, maybe to platform ("is this posixish" # check or something) if sys.platform == "win32": + working_modules["_winreg"] = None # unix only modules del working_modules["crypt"] del working_modules["fcntl"] @@ -48,9 +49,9 @@ del working_modules["bz2"] if sys.platform == "sunos5": - del working_modules['mmap'] # depend on ctypes, can'T get at c-level 'errono' + del working_modules['mmap'] # depend on ctypes, can't get at c-level 'errono' del working_modules['rctime'] # depend on ctypes, missing tm_zone/tm_gmtoff - del working_modules['signal'] # depend on ctypes, can'T get at c-level 'errono' + del working_modules['signal'] # depend on ctypes, can't get at c-level 'errono' del working_modules['fcntl'] # LOCK_NB not defined del working_modules["_minimal_curses"] del working_modules["termios"] Added: pypy/trunk/pypy/doc/config/objspace.usemodules._winreg.txt ============================================================================== --- (empty file) +++ pypy/trunk/pypy/doc/config/objspace.usemodules._winreg.txt Fri Feb 20 10:41:24 2009 @@ -0,0 +1,2 @@ +Use the built-in '_winreg' module, provides access to the Windows registry. +This module is expected to be working and is included by default on Windows. From afa at codespeak.net Fri Feb 20 11:32:04 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 11:32:04 +0100 (CET) Subject: [pypy-svn] r62045 - pypy/trunk/pypy/tool Message-ID: <20090220103204.0022C169E92@codespeak.net> Author: afa Date: Fri Feb 20 11:32:02 2009 New Revision: 62045 Modified: pypy/trunk/pypy/tool/watchdog_nt.py Log: Do not require the pywin32 module to be installed. It's much more likely that we have a working ctypes... Modified: pypy/trunk/pypy/tool/watchdog_nt.py ============================================================================== --- pypy/trunk/pypy/tool/watchdog_nt.py (original) +++ pypy/trunk/pypy/tool/watchdog_nt.py Fri Feb 20 11:32:02 2009 @@ -1,6 +1,6 @@ import sys, os import threading -import win32api, pywintypes +import ctypes PROCESS_TERMINATE = 0x1 @@ -11,10 +11,7 @@ global timedout timedout = True sys.stderr.write("="*26 + "timedout" + "="*26 + "\n") - try: - win32api.TerminateProcess(pid, 1) - except pywintypes.error: - pass + ctypes.windll.kernel32.TerminateProcess(pid, 1) pid = os.spawnv(os.P_NOWAIT, sys.argv[2], sys.argv[2:]) From fijal at codespeak.net Fri Feb 20 13:54:38 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Feb 2009 13:54:38 +0100 (CET) Subject: [pypy-svn] r62048 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090220125438.E4F12169EBB@codespeak.net> Author: fijal Date: Fri Feb 20 13:54:36 2009 New Revision: 62048 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: A bit of progress, more specific: * Fix virtual lists to work * Disable lazy lists, for various reasons * Progress towards rpythonization Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/graphpage.py Fri Feb 20 13:54:36 2009 @@ -68,10 +68,10 @@ _prev = Box._extended_display try: Box._extended_display = False - if len(self.graphs) > 1: - graphs = self.graphs[1:] - else: - graphs = self.graphs + #if len(self.graphs) > 1: + # graphs = self.graphs[1:] + #else: + graphs = self.graphs for i, graph in enumerate(graphs): self.gengraph(graph, i) finally: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Fri Feb 20 13:54:36 2009 @@ -63,6 +63,21 @@ # structures in case they are GcStruct inheriting from OBJECT. testing_gcstruct2vtable[GCSTRUCT] = vtable +def populate_type_cache(graphs, cpu): + cache = {} + for graph in graphs: + for block in graph.iterblocks(): + for op in block.operations: + if op.opname == 'malloc': + STRUCT = op.args[0].value + if isinstance(STRUCT, lltype.GcStruct): + vtable = get_vtable_for_gcstruct(cpu, STRUCT) + if vtable: + vt = cpu.cast_adr_to_int( + llmemory.cast_ptr_to_adr(vtable)) + cache[vt] = cpu.sizeof(STRUCT) + return cache + testing_gcstruct2vtable = {} # ____________________________________________________________ @@ -86,7 +101,7 @@ for guard in ['guard_no_exception', 'guard_true', 'guard_false', 'guard_value', 'guard_class']: - always_pure_operations[guard] = True - operation_never_raises[guard] = True + always_pure_operations[guard] = None + operation_never_raises[guard] = None setup() Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 20 13:54:36 2009 @@ -54,9 +54,9 @@ assert isinstance(ld, ListDescr) alloc_offset = len(self.list_allocations) malloc_func = ld.malloc_func - assert instnode.known_length != -1 + assert instnode.cursize != -1 self.list_allocations.append((malloc_func, - instnode.known_length)) + instnode.cursize)) res = (alloc_offset + 1) << 16 else: alloc_offset = len(self.allocations) @@ -69,7 +69,7 @@ if isinstance(instnode.cls.source, ListDescr): ld = instnode.cls.source x = (alloc_offset + 1) << 16 - assert ofs < instnode.known_length + assert ofs < instnode.cursize self.setitems.append((ld.setfunc, x, ofs, num)) else: self.setfields.append((alloc_offset, ofs, num)) @@ -87,11 +87,6 @@ liveboxes.append(box) return res -class TypeCache(object): - pass -type_cache = TypeCache() # XXX remove me later -type_cache.class_size = {} - class InstanceNode(object): def __init__(self, source, escaped=True, startbox=False, const=False): if isinstance(source, Const): @@ -108,18 +103,8 @@ self.cleanfields = {} self.dirtyfields = {} self.expanded_fields = {} - self.known_length = -1 - - def set_known_length(self, val): - if val != -1: - print "Setting: %r to %d" % (self, val) - assert val >= -1 - self._kl = val - - def get_known_length(self): - return self._kl - - known_length = property(get_known_length, set_known_length) + self.origsize = -1 + self.cursize = -1 def escape_if_startbox(self, memo): if self in memo: @@ -155,8 +140,11 @@ return FixedClassSpecNode(known_class) if not other.escaped: if (isinstance(known_class, ListDescr) - and self.known_length != other.known_length): - XXX # XXX think + and self.cursize != other.origsize): + # or DelayedListSpecNode, later on + self.escaped = True + other.escaped = True + return FixedListSpecNode(known_class) fields = [] if self is other: d = other.curfields.copy() @@ -174,7 +162,7 @@ fields.append((ofs, specnode)) if isinstance(known_class, ListDescr): return VirtualListSpecNode(known_class, fields, - other.known_length) + other.cursize) return VirtualInstanceSpecNode(known_class, fields) if not other.virtualized and self.expanded_fields: fields = [] @@ -285,15 +273,17 @@ self.dependency_graph.append((instnode, fieldnode)) instnode.origfields[field] = fieldnode self.nodes[box] = fieldnode - #if self.first_escaping_op: - # instnode.expanded_fields[field] = None + if (self.first_escaping_op and + instnode.cls and + not isinstance(instnode.cls.source, ListDescr)): + instnode.expanded_fields[field] = None def find_nodes_insert(self, instnode, field, fieldnode): for ofs, node in instnode.curfields.items(): if ofs >= field: instnode.curfields[ofs + 1] = node instnode.curfields[field] = fieldnode - instnode.known_length = instnode.known_length + 1 + instnode.cursize += 1 self.dependency_graph.append((instnode, fieldnode)) def find_nodes(self): @@ -319,7 +309,9 @@ self.first_escaping_op = False if (isinstance(op.args[1], ConstInt) or self.nodes[op.args[1]].const): - instnode.known_length = self.getsource(op.args[1]).getint() + size = self.getsource(op.args[1]).getint() + instnode.cursize = size + instnode.origsize = size # XXX following guard_builtin will set the # correct class, otherwise it's a mess continue @@ -329,9 +321,12 @@ instnode.cls = InstanceNode(op.args[1]) continue elif opname == 'guard_len': - if instnode.known_length == -1: + instnode = self.nodes[op.args[0]] + if instnode.cursize == -1: instnode = self.nodes[op.args[0]] - instnode.known_length = op.args[1].getint() + size = op.args[1].getint() + instnode.cursize = size + instnode.origsize = size continue elif opname == 'setfield_gc': instnode = self.getnode(op.args[0]) @@ -356,10 +351,9 @@ self.nodes[op.args[2]].const): field = self.getsource(fieldbox).getint() if field < 0: - field = instnode.known_length + field + field = instnode.cursize + field box = op.results[0] self.find_nodes_getfield(instnode, field, box) - print instnode, instnode.curfields, instnode.known_length continue else: instnode.escaped = True @@ -369,36 +363,33 @@ elif opname == 'append': instnode = self.getnode(op.args[1]) assert isinstance(instnode.cls.source, ListDescr) - if instnode.known_length != -1: - field = instnode.known_length - instnode.known_length = instnode.known_length + 1 + if instnode.cursize != -1: + field = instnode.cursize + instnode.cursize += 1 self.find_nodes_setfield(instnode, field, self.getnode(op.args[2])) - print instnode, instnode.curfields, instnode.known_length continue elif opname == 'insert': instnode = self.getnode(op.args[1]) assert isinstance(instnode.cls.source, ListDescr) - if instnode.known_length != -1: + if instnode.cursize != -1: fieldbox = self.getsource(op.args[2]) assert isinstance(fieldbox, Const) or fieldbox.const field = fieldbox.getint() if field < 0: - field = instnode.known_length + field + field = instnode.cursize + field self.find_nodes_insert(instnode, field, self.getnode(op.args[3])) - print instnode, instnode.curfields, instnode.known_length continue elif opname == 'pop': instnode = self.getnode(op.args[1]) assert isinstance(instnode.cls.source, ListDescr) - if instnode.known_length != -1: - instnode.known_length = instnode.known_length - 1 - field = instnode.known_length + if instnode.cursize != -1: + instnode.cursize -= 1 + field = instnode.cursize self.find_nodes_getfield(instnode, field, op.results[0]) if field in instnode.curfields: del instnode.curfields[field] - print instnode, instnode.curfields, instnode.known_length continue self.nodes[op.results[0]] = InstanceNode(op.results[0], escaped=True) @@ -408,7 +399,7 @@ elif opname == 'len' or opname == 'listnonzero': instnode = self.getnode(op.args[1]) if not instnode.escaped: - assert instnode.known_length != -1 + assert instnode.cursize != -1 lgtbox = op.results[0].constbox() self.nodes[op.results[0]] = InstanceNode(lgtbox, const=True) continue @@ -419,11 +410,10 @@ or self.nodes[op.args[2]].const): field = self.getsource(fieldbox).getint() if field < 0: - field = instnode.known_length + field - assert field < instnode.known_length + field = instnode.cursize + field + assert field < instnode.cursize self.find_nodes_setfield(instnode, field, self.getnode(op.args[3])) - print "XXX", instnode, " <- ", self.getnode(fieldbox) continue else: self.dependency_graph.append((instnode, @@ -571,7 +561,7 @@ def optimize_getfield(self, instnode, ofs, box): if instnode.virtual or instnode.virtualized: if ofs < 0: - ofs = instnode.known_length + ofs + ofs = instnode.cursize + ofs assert ofs in instnode.curfields return True # this means field is never actually elif ofs in instnode.cleanfields: @@ -584,7 +574,7 @@ def optimize_setfield(self, instnode, ofs, valuenode, valuebox): if instnode.virtual or instnode.virtualized: if ofs < 0: - ofs = instnode.known_length + ofs + ofs = instnode.cursize + ofs instnode.curfields[ofs] = valuenode else: assert not valuenode.virtual @@ -598,7 +588,7 @@ if ofs >= field: instnode.curfields[ofs + 1] = node instnode.curfields[field] = valuenode - instnode.known_length = instnode.known_length + 1 + instnode.cursize += 1 def optimize_loop(self): self.ready_results = {} @@ -655,9 +645,10 @@ elif opname == 'guard_len': # it should be completely gone, because if it escapes # we don't virtualize it anymore - if not instnode.escaped and instnode.known_length == -1: + instnode = self.nodes[op.args[0]] + if not instnode.escaped and instnode.cursize == -1: instnode = self.nodes[op.args[0]] - instnode.known_length = op.args[1].getint() + instnode.cursize = op.args[1].getint() continue elif opname == 'guard_nonvirtualized': instnode = self.nodes[op.args[0]] @@ -702,9 +693,6 @@ if not instnode.escaped: instnode.virtual = True assert instnode.cls is not None - size = op.args[0].getint() - key = instnode.cls.source.getint() - type_cache.class_size[key] = size continue elif opname == 'newlist': instnode = self.nodes[op.results[0]] @@ -712,9 +700,9 @@ if not instnode.escaped: instnode.virtual = True valuesource = self.getsource(op.args[2]) - instnode.known_length = op.args[1].getint() + instnode.cursize = op.args[1].getint() curfields = {} - for i in range(instnode.known_length): + for i in range(instnode.cursize): curfields[i] = InstanceNode(valuesource, const=True) instnode.curfields = curfields @@ -723,8 +711,8 @@ instnode = self.nodes[op.args[1]] valuenode = self.getnode(op.args[2]) if not instnode.escaped: - ofs = instnode.known_length - instnode.known_length = instnode.known_length + 1 + ofs = instnode.cursize + instnode.cursize += 1 self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) continue elif opname == 'insert': @@ -737,8 +725,8 @@ elif opname == 'pop': instnode = self.nodes[op.args[1]] if not instnode.escaped: - instnode.known_length = instnode.known_length - 1 - ofs = instnode.known_length + instnode.cursize -= 1 + ofs = instnode.cursize if self.optimize_getfield(instnode, ofs, op.results[0]): del instnode.curfields[ofs] continue @@ -859,16 +847,14 @@ return allocated_lists[(index - 1) >> 16] return allocated_boxes[index] -def rebuild_boxes_from_guard_failure(guard_op, history, boxes_from_frame): +def rebuild_boxes_from_guard_failure(guard_op, metainterp, boxes_from_frame): allocated_boxes = [] allocated_lists = [] storage = guard_op.storage_info + history = metainterp.history for vtable in storage.allocations: - # XXX virtual object that came from the outside (stored on - # a virtualizable) has no entry in type_cache, probably - # we need to attach some info to guard_class - sizebox = ConstInt(type_cache.class_size[vtable]) + sizebox = ConstInt(metainterp.class_sizes[vtable]) vtablebox = ConstInt(vtable) [instbox] = history.execute_and_record('new_with_vtable', [sizebox, vtablebox], Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Feb 20 13:54:36 2009 @@ -10,7 +10,8 @@ from pypy.jit.metainterp.history import (Const, ConstInt, ConstPtr, Box, BoxInt, BoxPtr, GuardOp) from pypy.jit.metainterp.compile import compile_new_loop, compile_new_bridge -from pypy.jit.metainterp.heaptracker import get_vtable_for_gcstruct +from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, + populate_type_cache) from pypy.jit.metainterp import codewriter, optimize # ____________________________________________________________ @@ -492,7 +493,7 @@ def generate_merge_point(self, pc, varargs): if isinstance(self.metainterp.history, history.BlackHole): raise self.metainterp.ContinueRunningNormally(varargs) - num_green_args = self.metainterp.warmrunnerdesc.num_green_args + num_green_args = self.metainterp.num_green_args for i in range(num_green_args): varargs[i] = self.implement_guard_value(pc, varargs[i]) @@ -659,8 +660,9 @@ class OOMetaInterp(object): + num_green_args = 0 - def __init__(self, portal_graph, cpu, stats, specialize): + def __init__(self, portal_graph, graphs, cpu, stats, specialize): self.portal_graph = portal_graph self.cpu = cpu self.stats = stats @@ -675,7 +677,9 @@ self.builtins_keys = [] self.builtins_values = [] self.builtins_seen = {} - + + self.class_sizes = populate_type_cache(graphs, self.cpu) + self._virtualizabledescs = {} def generate_bytecode(self, policy): @@ -772,7 +776,7 @@ self.jump_after_guard_failure(guard_failure, loop, resargs) def designate_target_loop(self, gmp, loop): - num_green_args = self.warmrunnerdesc.num_green_args + num_green_args = self.num_green_args residual_args = self.get_residual_args(loop, gmp.argboxes[num_green_args:]) return (loop, residual_args) @@ -784,7 +788,7 @@ i, residual_args[i]) def compile(self, original_boxes, live_arg_boxes): - num_green_args = self.warmrunnerdesc.num_green_args + num_green_args = self.num_green_args for i in range(num_green_args): box1 = original_boxes[i] box2 = live_arg_boxes[i] @@ -803,7 +807,7 @@ return loop def compile_bridge(self, guard_failure, original_boxes, live_arg_boxes): - num_green_args = self.warmrunnerdesc.num_green_args + num_green_args = self.num_green_args mp = history.ResOperation('catch', original_boxes, []) mp.coming_from = guard_failure.guard_op self.history.operations.insert(0, mp) @@ -833,7 +837,7 @@ def initialize_state_from_start(self, args): self.create_empty_history() - num_green_args = self.warmrunnerdesc.num_green_args + num_green_args = self.num_green_args original_boxes = [] for i in range(len(args)): value = args[i] @@ -851,7 +855,7 @@ def initialize_state_from_guard_failure(self, guard_failure): # guard failure: rebuild a complete MIFrame stack - if self.warmrunnerdesc.state.must_compile_from_failure(guard_failure): + if self.state.must_compile_from_failure(guard_failure): self.history = history.History(self.cpu) else: self.history = history.BlackHole(self.cpu) @@ -869,7 +873,7 @@ boxes_from_frame.append(newbox) if guard_op.storage_info is not None: newboxes = optimize.rebuild_boxes_from_guard_failure( - guard_op, self.history, boxes_from_frame) + guard_op, self, boxes_from_frame) else: # xxx for tests only newboxes = boxes_from_frame Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Fri Feb 20 13:54:36 2009 @@ -16,7 +16,9 @@ stats = history.Stats() cpu = CPUClass(rtyper, stats, False) graph = rtyper.annotator.translator.graphs[0] - return pyjitpl.OOMetaInterp(graph, cpu, stats, False), rtyper + metainterp = pyjitpl.OOMetaInterp(graph, [], cpu, stats, False) + metainterp.num_green_args = 0 + return metainterp, rtyper class JitMixin: basic = True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dlist.py Fri Feb 20 13:54:36 2009 @@ -1,5 +1,6 @@ import py +py.test.skip("turned off for now") from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin @@ -19,7 +20,7 @@ res = self.meta_interp(f, [10]) assert res == f(10) self.check_loops(getitem=0, setitem=1, guard_exception=0, - guard_no_exception=0) + guard_no_exception=1) def test_list_escapes(self): myjitdriver = JitDriver(greens = [], reds = ['n', 'l']) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 20 13:54:36 2009 @@ -10,7 +10,7 @@ Jump, GuardOp) from pypy.jit.metainterp.optimize import (PerfectSpecializer, CancelInefficientLoop, VirtualInstanceSpecNode, FixedClassSpecNode, - rebuild_boxes_from_guard_failure, type_cache, AllocationStorage, + rebuild_boxes_from_guard_failure, AllocationStorage, NotSpecNode) cpu = runner.CPU(None) @@ -74,6 +74,7 @@ ofs_next = runner.CPU.fielddescrof(NODE, 'next') ofs_value = runner.CPU.fielddescrof(NODE, 'value') size_of_node = runner.CPU.sizeof(NODE) + sizebox = ConstInt(size_of_node) # startnode = lltype.malloc(NODE) startnode.value = 20 @@ -88,11 +89,12 @@ sum2 = BoxInt(0 + startnode.value) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), - ResOperation('new_with_vtable', [ConstInt(size_of_node), + ResOperation('new_with_vtable', [sizebox, ConstAddr(node_vtable, cpu)], [n2]), ResOperation('setfield_gc', [n2, ConstInt(ofs_value), v2], []), Jump('jump', [sum2, n2], []), @@ -138,7 +140,8 @@ locals().update(A.__dict__) # :-) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('escape', [n1], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), @@ -194,7 +197,8 @@ locals().update(A.__dict__) # :-) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('some_escaping_operation', [n1], []), # <== escaping ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), @@ -250,7 +254,8 @@ locals().update(A.__dict__) # :-) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node2_vtable, cpu), + sizebox], []), # the only difference is different vtable ^^^^^^^^^^^^ ResOperation('getfield', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), @@ -272,7 +277,8 @@ locals().update(A.__dict__) # :-) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -315,22 +321,29 @@ return ['allocated'] else: return [] + + class FakeMetaInterp(object): + def __init__(self): + self.history = FakeHistory() + self.class_sizes = {cpu.cast_adr_to_int(node_vtable_adr): + E.size_of_node} spec = PerfectSpecializer(Loop(E.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() guard_op = spec.loop.operations[-2] - fake_history = FakeHistory() v_sum_b = BoxInt(13) v_v_b = BoxInt(14) - newboxes = rebuild_boxes_from_guard_failure(guard_op, fake_history, - [v_sum_b, v_v_b]) vt = cpu.cast_adr_to_int(node_vtable_adr) - assert fake_history.ops == [ - ('new_with_vtable', [ConstInt(type_cache.class_size[vt]), ConstInt(vt)]), + fake_metainterp = FakeMetaInterp() + newboxes = rebuild_boxes_from_guard_failure(guard_op, fake_metainterp, + [v_sum_b, v_v_b]) + expected = [ + ('new_with_vtable', [E.sizebox, ConstInt(vt)]), ('setfield_gc', ['allocated', ConstInt(E.ofs_value), v_v_b]) ] + assert expected == fake_metainterp.history.ops assert newboxes == [v_sum_b, 'allocated'] # ____________________________________________________________ @@ -345,7 +358,8 @@ vbool3 = BoxInt(1) ops = [ MergePoint('merge_point', [sum, n1, n3], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -394,7 +408,8 @@ v4 = BoxInt(124) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -531,7 +546,8 @@ v3 = BoxInt(4) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -563,7 +579,8 @@ v3 = BoxInt(4) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -598,7 +615,8 @@ v3 = BoxInt(4) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -628,7 +646,8 @@ v3 = BoxInt(4) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -661,7 +680,8 @@ v3 = BoxInt(4) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), @@ -692,7 +712,8 @@ v3 = BoxInt(4) ops = [ MergePoint('merge_point', [sum, n1], []), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), ResOperation('int_sub', [v, ConstInt(1)], [v2]), ResOperation('int_add', [sum, v], [sum2]), Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Fri Feb 20 13:54:36 2009 @@ -1,5 +1,4 @@ import py -py.test.skip("unsupported list ops") from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, hint @@ -20,6 +19,7 @@ assert res == 9 def test_list_operations(self): + py.test.skip("pop(int) not supported") class FooBar: def __init__(self, z): self.z = z Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Fri Feb 20 13:54:36 2009 @@ -166,13 +166,15 @@ locals().update(B.__dict__) n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, frame.node)) v2 = BoxInt(13) + sizebox = ConstInt(cpu.sizeof(NODE)) ops = [ MergePoint('merge_point', [fr], []), ResOperation('guard_nonvirtualized', [fr, ConstAddr(xy_vtable, cpu), ConstInt(ofs_node)], []), # ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n1]), - ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu)], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), ResOperation('getfield_gc', [n1, ConstInt(ofs_value)], [v]), # ResOperation('getfield_gc', [fr, ConstInt(ofs_node)], [n2]), Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py Fri Feb 20 13:54:36 2009 @@ -145,6 +145,59 @@ res = self.meta_interp(f, [10]) assert res == f(10) + def test_virtual_on_virtualizable(self): + myjitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) + + class Stuff(object): + def __init__(self, x): + self.x = x + + class Stuff2(Stuff): + pass + + class Frame(object): + _virtualizable2_ = True + def __init__(self, x): + self.stuff = Stuff(x) + + def f(n): + frame = Frame(3) + while n > 0: + myjitdriver.can_enter_jit(frame=frame, n=n) + myjitdriver.jit_merge_point(frame=frame, n=n) + if isinstance(frame.stuff, Stuff2): + return 2 + n -= frame.stuff.x + return n + + res = self.meta_interp(f, [30]) + assert res == f(30) + + def test_unequal_list_lengths_cannot_be_virtual(self): + jitdriver = JitDriver(greens = [], reds = ['frame', 'n'], + virtualizables = ['frame']) + + class Frame(object): + _virtualizable2_ = True + def __init__(self): + self.l = [] + + def f(n): + frame = Frame() + while n > 0: + jitdriver.can_enter_jit(n=n, frame=frame) + jitdriver.jit_merge_point(n=n, frame=frame) + frame.l.append(n) + n -= 1 + sum = 0 + for i in range(len(frame.l)): + sum += frame.l[i] + return sum + + res = self.meta_interp(f, [20]) + assert res == f(20) + def test_external_read(self): py.test.skip("Fails") class Frame(object): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_warmspot.py Fri Feb 20 13:54:36 2009 @@ -42,8 +42,23 @@ except Exit, e: return e.result - res = self.meta_interp(main, [1], interpreter_loop) + res = self.meta_interp(main, [1]) assert res == 21 + def test_reentry(self): + mydriver = JitDriver(reds = ['n'], greens = []) + + def f(n): + while n > 0: + mydriver.can_enter_jit(n=n) + mydriver.jit_merge_point(n=n) + if n % 20 == 0: + n -= 2 + n -= 1 + + res = self.meta_interp(f, [60]) + assert res == f(30) + + class TestLLWarmspot(WarmspotTests): pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py Fri Feb 20 13:54:36 2009 @@ -1,47 +1,18 @@ import py -py.test.skip("XXX") -from pyjitpl import ll_meta_interp, get_stats -from rpyjitpl import rpython_ll_meta_interp -from test import test_basic - +py.test.skip("XXX WiP") +from pypy.jit.metainterp.warmspot import rpython_ll_meta_interp, ll_meta_interp +from pypy.jit.metainterp.test import test_basic +from pypy.rlib.jit import JitDriver class TestBasic: - def test_dummy(self): - def f(x): - return x - res = ll_meta_interp(f, [42]) - assert res == 42 - res = rpython_ll_meta_interp(f, [42], loops=0) - assert res == 42 - - def test_basic(self): - def f(x, y): - return x + y - res = ll_meta_interp(f, [40, 2]) - assert res == 42 - res = rpython_ll_meta_interp(f, [40, 2], loops=0) - assert res == 42 - - def test_if(self): - def f(x, y, z): - if x: - return y - else: - return z - res = ll_meta_interp(f, [1, 40, 2]) - assert res == 40 - res = ll_meta_interp(f, [1, 40, 2]) - assert res == 40 - res = rpython_ll_meta_interp(f, [1, 40, 2], loops=0) - assert res == 40 - res = rpython_ll_meta_interp(f, [0, 40, 2], loops=0) - assert res == 2 - def test_loop_1(self): + jitdriver = JitDriver(greens = [], reds = ['i', 'total']) def f(i): total = 0 while i > 3: + jitdriver.can_enter_jit(i=i, total=total) + jitdriver.jit_merge_point(i=i, total=total) total += i i -= 1 return total * 10 @@ -64,31 +35,6 @@ res = rpython_ll_meta_interp(f, [17], loops=2) assert res == (17+14+11+8+7+6+5+4) * 10 - def test_ptr_very_simple(self): - class A: - pass - a = A() - def f(i): - a.i = i - return a.i + 2 - res = ll_meta_interp(f, [17]) - assert res == 19 - res = rpython_ll_meta_interp(f, [17]) - assert res == 19 - - def test_ptr_simple(self): - class A: - pass - def f(i): - a = A() - a.i = i - return a.i + 2 - res = ll_meta_interp(f, [17]) - assert res == 19 - res = rpython_ll_meta_interp(f, [17], loops=0) - assert res == 19 - - class LLInterpJitMixin: type_system = 'lltype' meta_interp = staticmethod(rpython_ll_meta_interp) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Fri Feb 20 13:54:36 2009 @@ -1,6 +1,7 @@ import sys from pypy.rpython.lltypesystem import lltype, llmemory, rclass -from pypy.rpython.annlowlevel import llhelper +from pypy.rpython.annlowlevel import llhelper, MixLevelHelperAnnotator +from pypy.annotation import model as annmodel from pypy.rpython.llinterp import LLException from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache from pypy.objspace.flow.model import SpaceOperation, Variable, Constant @@ -28,6 +29,18 @@ warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests return interp.eval_graph(graph, args) +def rpython_ll_meta_interp(function, args, loops=None, **kwds): + kwds['translate_support_code'] = True + interp, graph = get_interpreter(function, args, backendopt=True, + inline_threshold=0) + clear_tcache() + translator = interp.typer.annotator.translator + warmrunnerdesc = WarmRunnerDesc(translator, **kwds) + warmrunnerdesc.state.set_param_threshold(3) # for tests + warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests + xxx + interp.eval_graph(boot, args) + def find_can_enter_jit(graphs): results = [] for graph in graphs: @@ -78,7 +91,8 @@ self.make_enter_function() self.rewrite_can_enter_jit() self.rewrite_jit_merge_point() - self.metainterp.warmrunnerdesc = self # allows call-backs + self.metainterp.num_green_args = self.num_green_args + self.metainterp.state = self.state def _freeze_(self): return True @@ -90,6 +104,8 @@ cpu = CPUClass(self.translator.rtyper, self.stats, translate_support_code) self.cpu = cpu + if translate_support_code: + self.annhelper = MixLevelHelperAnnotator(self.translator.rtyper) graphs = self.translator.graphs self.jit_merge_point_pos = find_jit_merge_point(graphs) graph, block, pos = self.jit_merge_point_pos @@ -102,7 +118,8 @@ self.translator.graphs.append(graph) self.portal_graph = graph self.jitdriver = block.operations[pos].args[1].value - self.metainterp = OOMetaInterp(graph, cpu, self.stats, specialize) + self.metainterp = OOMetaInterp(graph, graphs, cpu, self.stats, + specialize) def make_enter_function(self): WarmEnterState = make_state_class(self) @@ -131,10 +148,9 @@ self.PORTAL_FUNCTYPE = lltype.FuncType(ALLARGS, RESTYPE) def rewrite_can_enter_jit(self): - assert not self.cpu.translate_support_code, "XXX for now" FUNC = self.JIT_ENTER_FUNCTYPE FUNCPTR = lltype.Ptr(FUNC) - jit_enter_fnptr = llhelper(FUNCPTR, self.maybe_enter_jit_fn) + jit_enter_fnptr = self.helper_func(FUNCPTR, self.maybe_enter_jit_fn) graphs = self.translator.graphs can_enter_jits = find_can_enter_jit(graphs) @@ -153,6 +169,14 @@ newop = SpaceOperation('direct_call', vlist, v_result) block.operations[index] = newop + def helper_func(self, FUNCPTR, func): + if not self.cpu.translate_support_code: + return llhelper(FUNCPTR, func) + FUNC = FUNCPTR.TO + args_s = [annmodel.lltype_to_annotation(ARG) for ARG in FUNC.ARGS] + s_result = annmodel.lltype_to_annotation(FUNC.RESULT) + return self.annhelper.delayedfunction(func, args_s, s_result) + def rewrite_jit_merge_point(self): # # Mutate the original portal graph from this: @@ -228,34 +252,39 @@ self.metainterp.ContinueRunningNormally = ContinueRunningNormally rtyper = self.translator.rtyper - def ll_portal_runner(*args): - while 1: - try: - return support.maybe_on_top_of_llinterp(rtyper, - portal_ptr)(*args) - except ContinueRunningNormally, e: - # XXX NOT RPYTHON - args = [] - for i, arg in enumerate(e.args): - v = arg.value - if lltype.typeOf(v) == llmemory.GCREF: - v = lltype.cast_opaque_ptr(PORTALFUNC.ARGS[i], v) - args.append(v) - except DoneWithThisFrame, e: - if e.resultbox is not None: - return e.resultbox.value - return - except ExitFrameWithException, e: - type = e.typebox.getaddr(self.metainterp.cpu) - type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE) - value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT)) - raise LLException(type, value) - if not self.cpu.translate_support_code: - portal_runner_ptr = llhelper(lltype.Ptr(PORTALFUNC), - ll_portal_runner) + def ll_portal_runner(*args): + while 1: + try: + return support.maybe_on_top_of_llinterp(rtyper, + portal_ptr)(*args) + except ContinueRunningNormally, e: + args = [] + for i, arg in enumerate(e.args): + v = arg.value + if lltype.typeOf(v) == llmemory.GCREF: + v = lltype.cast_opaque_ptr(PORTALFUNC.ARGS[i], + v) + args.append(v) + except DoneWithThisFrame, e: + if e.resultbox is not None: + return e.resultbox.value + return + except ExitFrameWithException, e: + type = e.typebox.getaddr(self.metainterp.cpu) + type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE) + value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT)) + raise LLException(type, value) + else: - xxx + def ll_portal_runner(*args): + while 1: + #try: + portal_ptr(*args) + #xexcept DoneWi + + portal_runner_ptr = self.helper_func(lltype.Ptr(PORTALFUNC), + ll_portal_runner) # ____________________________________________________________ # Now mutate origportalgraph to end with a call to portal_runner_ptr @@ -276,6 +305,8 @@ origblock.exitswitch = None origblock.recloseblock(Link([v_result], origportalgraph.returnblock)) checkgraph(origportalgraph) + if self.cpu.translate_support_code: + self.annhelper.finish() def decode_hp_hint_args(op): @@ -318,8 +349,8 @@ __slots__ = 'counter' class MachineCodeEntryPoint(StateCell): - def __init__(self, mc, *greenargs): - self.mc = mc + def __init__(self, mp, *greenargs): + self.mp = mp self.next = Counter(0) i = 0 for name in green_args_names: @@ -378,16 +409,17 @@ self.cells[argshash] = Counter(n) return #interp.debug_trace("jit_compile", *greenargs) - return self.compile_and_run(argshash, *args) + self.compile_and_run(argshash, *args) else: + raise NotImplementedError("bridges to compiled code") # machine code was already compiled for these greenargs # (or we have a hash collision) - XXX assert isinstance(cell, MachineCodeEntryPoint) if cell.equalkey(*greenargs): - return cell.mc + self.run(cell, *args) else: - return self.handle_hash_collision(cell, argshash, *args) + xxx + self.handle_hash_collision(cell, argshash, *args) maybe_compile_and_run._dont_inline_ = True def handle_hash_collision(self, cell, argshash, *args): From fijal at codespeak.net Fri Feb 20 13:55:18 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Feb 2009 13:55:18 +0100 (CET) Subject: [pypy-svn] r62049 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090220125518.2F607169EC4@codespeak.net> Author: fijal Date: Fri Feb 20 13:55:17 2009 New Revision: 62049 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: a bit of fixes to the previous checkin Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Feb 20 13:55:17 2009 @@ -17,6 +17,8 @@ from pypy.jit.metainterp import heaptracker from pypy.jit.backend.llgraph import symbolic +from pypy.rlib.objectmodel import ComputedIntSymbolic + import py from pypy.tool.ansi_print import ansi_log log = py.log.Producer('runner') @@ -387,6 +389,9 @@ values.insert(0, result_type) exec_counters = _stats.exec_counters exec_counters[opname] = exec_counters.get(opname, 0) + 1 + for i in range(len(values)): + if isinstance(values[i], ComputedIntSymbolic): + values[i] = values[i].compute_fn() res = ophandler(*values) if verbose: argtypes, restype = TYPES[opname] @@ -871,6 +876,7 @@ setannotation(compile_add_jump_target, annmodel.s_None) setannotation(compile_add_failnum, annmodel.s_None) setannotation(compile_from_guard, annmodel.s_None) +setannotation(compile_add_livebox, annmodel.s_None) setannotation(new_frame, s_Frame) setannotation(frame_clear, annmodel.s_None) From fijal at codespeak.net Fri Feb 20 14:03:18 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 20 Feb 2009 14:03:18 +0100 (CET) Subject: [pypy-svn] r62050 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090220130318.303DA169ED4@codespeak.net> Author: fijal Date: Fri Feb 20 14:03:17 2009 New Revision: 62050 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py Log: hint for the list type. otherwise it's a real mess to guess Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py Fri Feb 20 14:03:17 2009 @@ -110,7 +110,8 @@ "_ll_resize_ge": _ll_list_resize_ge, "_ll_resize_le": _ll_list_resize_le, "_ll_resize": _ll_list_resize, - })) + }), + hints = {'list': True}) ) def compact_repr(self): From afa at codespeak.net Fri Feb 20 15:57:50 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 15:57:50 +0100 (CET) Subject: [pypy-svn] r62051 - pypy/trunk/pypy/rpython/tool Message-ID: <20090220145750.8EA76169EC0@codespeak.net> Author: afa Date: Fri Feb 20 15:57:48 2009 New Revision: 62051 Modified: pypy/trunk/pypy/rpython/tool/rffi_platform.py Log: fix typo in assertion Modified: pypy/trunk/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/trunk/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/trunk/pypy/rpython/tool/rffi_platform.py Fri Feb 20 15:57:48 2009 @@ -510,7 +510,7 @@ name = '%s_%d' % (prefix, i) field = Field(name, ctype) for i in range(offset, offset+size): - assert layout[i] is None, "%s overlaps %r" % (fieldname, layout[i]) + assert layout[i] is None, "%s overlaps %r" % (name, layout[i]) layout[i] = field return field From afa at codespeak.net Fri Feb 20 16:05:31 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 16:05:31 +0100 (CET) Subject: [pypy-svn] r62052 - pypy/trunk/pypy/rpython/module/test Message-ID: <20090220150531.C38641684F9@codespeak.net> Author: afa Date: Fri Feb 20 16:05:31 2009 New Revision: 62052 Modified: pypy/trunk/pypy/rpython/module/test/test_ll_os.py Log: Fix test: python is not always in the system PATH Modified: pypy/trunk/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/trunk/pypy/rpython/module/test/test_ll_os.py (original) +++ pypy/trunk/pypy/rpython/module/test/test_ll_os.py Fri Feb 20 16:05:31 2009 @@ -56,7 +56,7 @@ def test_system(): filename = str(udir.join('test_system.txt')) - arg = 'python -c "print 1+1" > %s' % filename + arg = '%s -c "print 1+1" > %s' % (sys.executable, filename) data = getllimpl(os.system)(arg) assert data == 0 assert file(filename).read().strip() == '2' From afa at codespeak.net Fri Feb 20 17:03:07 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 17:03:07 +0100 (CET) Subject: [pypy-svn] r62053 - in pypy/trunk/pypy: rlib rpython/module rpython/module/test Message-ID: <20090220160307.0F0FB169E4A@codespeak.net> Author: afa Date: Fri Feb 20 17:03:05 2009 New Revision: 62053 Modified: pypy/trunk/pypy/rlib/rwin32.py pypy/trunk/pypy/rpython/module/ll_os_stat.py pypy/trunk/pypy/rpython/module/test/test_ll_os_path.py Log: On Windows, the libc stat() is flawed: stat('c:/temp') works but stat('c:/temp/') does not find the directory... Use another implementation based on the Win32 API, like cpython does. I tried to find why os.stat() cannot be run on the llinterpreter on Unix. I found several reasons: - the regular implementation cannot run, because fstat is not exported by the libc (header files specify "asmlinkage" in the declarations) - the fake implementation should call hlstr(arg), so that the cpython function can be called. - It seems that the llinterpreter flows and annotates the *cpython* function os.path.isdir (yes, the one in /usr/lib/python2.5/posixpath.py). By luck this function is RPython, so it's probably not a big deal. - os.stat may raise an exception, which is not caught by isdir(). This may be because of the different levels of interpretation. In short, rffi seems much cleaner... and allowed me to unskip a test on Windows. It's very possible that I broke something important though; will watch the buildbots. Modified: pypy/trunk/pypy/rlib/rwin32.py ============================================================================== --- pypy/trunk/pypy/rlib/rwin32.py (original) +++ pypy/trunk/pypy/rlib/rwin32.py Fri Feb 20 17:03:05 2009 @@ -81,6 +81,8 @@ [DWORD, rffi.VOIDP, DWORD, DWORD, rffi.CCHARP, DWORD, rffi.VOIDP], DWORD) + _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE) + # A bit like strerror... def FormatError(code): Modified: pypy/trunk/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/trunk/pypy/rpython/module/ll_os_stat.py Fri Feb 20 17:03:05 2009 @@ -13,9 +13,6 @@ from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo -# XXX on Windows, stat() is flawed; see CPython's posixmodule.c for -# an implementation based on the Win32 API - # NOTE: float times are disabled for now, for simplicity. They make the life # of OO backends more complicated because for them we try to not depend on # the details of the platform on which we do the translation. Also, they @@ -212,7 +209,7 @@ os_mystat = rffi.llexternal(c_func_name, [ARG1, STAT_STRUCT], rffi.INT, compilation_info=compilation_info) - def os_mystat_llimpl(arg): + def posix_stat_llimpl(arg): stresult = lltype.malloc(STAT_STRUCT.TO, flavor='raw') try: if arg_is_path: @@ -226,7 +223,7 @@ finally: lltype.free(stresult, flavor='raw') - def fakeimpl(arg): + def posix_fakeimpl(arg): st = getattr(os, name)(arg) fields = [TYPE for fieldname, TYPE in LL_STAT_FIELDS] TP = TUPLE_TYPE(fields) @@ -240,20 +237,27 @@ s_arg = str else: s_arg = int - register_external(getattr(os, name), [s_arg], s_StatResult, - "ll_os.ll_os_%s" % (name,), - llimpl=func_with_new_name(os_mystat_llimpl, - 'os_%s_llimpl' % (name,)), - llfakeimpl=func_with_new_name(fakeimpl, - 'os_%s_fake' % (name,))) + + if sys.platform != 'win32': + register_external( + getattr(os, name), [s_arg], s_StatResult, + "ll_os.ll_os_%s" % (name,), + llimpl=func_with_new_name(posix_stat_llimpl, + 'os_%s_llimpl' % (name,)), + llfakeimpl=func_with_new_name(posix_fakeimpl, + 'os_%s_fake' % (name,)), + ) + else: + # See Win32 implementation below + register_external( + getattr(os, name), [s_arg], s_StatResult, + "ll_os.ll_os_%s" % (name,), + llimpl=func_with_new_name(globals()['win32_%s_llimpl' % (name,)], + 'os_%s_llimpl' % (name,)), + ) # ____________________________________________________________ -if 0: - XXX - """ - disabled for now: - error codes are different when returned from the Win32 API, - which makes things a mess that I don't want to tackle now... - """ +if sys.platform == 'win32': # The CRT of Windows has a number of flaws wrt. its stat() implementation: # - for when we implement subsecond resolution in RPython, time stamps # would be restricted to second resolution @@ -261,42 +265,139 @@ # UTC and local time # Therefore, we implement our own stat, based on the Win32 API directly. from pypy.rpython.tool import rffi_platform as platform + from pypy.translator.tool.cbuild import ExternalCompilationInfo + from rlib import rwin32 assert len(STAT_FIELDS) == 10 # no extra fields on Windows - FILETIME = rffi.CStruct('_FILETIME', ('dwLowDateTime', rffi.LONG), - ('dwHighDateTime', rffi.LONG)) + class CConfig: - GET_FILEEX_INFO_LEVELS = platform.SimpleType('GET_FILEEX_INFO_LEVELS', - rffi.INT) + _compilation_info_ = ExternalCompilationInfo( + includes = ['windows.h', 'winbase.h', 'sys/stat.h'], + ) + GetFileExInfoStandard = platform.ConstantInteger( 'GetFileExInfoStandard') + FILE_ATTRIBUTE_DIRECTORY = platform.ConstantInteger( + 'FILE_ATTRIBUTE_DIRECTORY') + FILE_ATTRIBUTE_READONLY = platform.ConstantInteger( + 'FILE_ATTRIBUTE_READONLY') + _S_IFDIR = platform.ConstantInteger('_S_IFDIR') + _S_IFREG = platform.ConstantInteger('_S_IFREG') + WIN32_FILE_ATTRIBUTE_DATA = platform.Struct( - '_WIN32_FILE_ATTRIBUTE_DATA', - [('dwFileAttributes', rffi.ULONG), - ('nFileSizeHigh', rffi.ULONG), - ('nFileSizeLow', rffi.ULONG), - ('ftCreationTime', FILETIME), - ('ftLastAccessTime', FILETIME), - ('ftCreationTime', FILETIME)]) + 'WIN32_FILE_ATTRIBUTE_DATA', + [('dwFileAttributes', rwin32.DWORD), + ('nFileSizeHigh', rwin32.DWORD), + ('nFileSizeLow', rwin32.DWORD), + ('ftCreationTime', rwin32.FILETIME), + ('ftLastAccessTime', rwin32.FILETIME), + ('ftLastWriteTime', rwin32.FILETIME)]) + + BY_HANDLE_FILE_INFORMATION = platform.Struct( + 'BY_HANDLE_FILE_INFORMATION', + [('dwFileAttributes', rwin32.DWORD), + ('nFileSizeHigh', rwin32.DWORD), + ('nFileSizeLow', rwin32.DWORD), + ('nNumberOfLinks', rwin32.DWORD), + ('nFileIndexHigh', rwin32.DWORD), + ('nFileIndexLow', rwin32.DWORD), + ('ftCreationTime', rwin32.FILETIME), + ('ftLastAccessTime', rwin32.FILETIME), + ('ftLastWriteTime', rwin32.FILETIME)]) globals().update(platform.configure(CConfig)) + GET_FILEEX_INFO_LEVELS = rffi.ULONG # an enumeration GetFileAttributesEx = rffi.llexternal( - 'GetFileAttributesExA', [rffi.CCHARP, - GET_FILEEX_INFO_LEVELS, - lltype.Ptr(WIN32_FILE_ATTRIBUTE_DATA)], - rffi.INT) + 'GetFileAttributesExA', + [rffi.CCHARP, GET_FILEEX_INFO_LEVELS, + lltype.Ptr(WIN32_FILE_ATTRIBUTE_DATA)], + rwin32.BOOL, + calling_conv='win') + + GetFileInformationByHandle = rffi.llexternal( + 'GetFileInformationByHandle', + [rwin32.HANDLE, lltype.Ptr(BY_HANDLE_FILE_INFORMATION)], + rwin32.BOOL, + calling_conv='win') + + def attributes_to_mode(attributes): + m = 0 + if attributes & FILE_ATTRIBUTE_DIRECTORY: + m |= _S_IFDIR | 0111 # IFEXEC for user,group,other + else: + m |= _S_IFREG + if attributes & FILE_ATTRIBUTE_READONLY: + m |= 0444 + else: + m |= 0666 + return m + + secs_between_epochs = lltype.r_ulonglong(11644473600) # Seconds between 1.1.1601 and 1.1.1970 + def FILE_TIME_to_time_t_nsec(filetime): + ft = (lltype.r_ulonglong(filetime.c_dwHighDateTime) << 32) + ft += filetime.c_dwLowDateTime + # FILETIME is in units of 100 nsec + nsec = (ft % 10000000) * 100 + time = (ft / 10000000) - secs_between_epochs + return time, nsec + + def attribute_data_to_stat(info): + st_mode = attributes_to_mode(info.c_dwFileAttributes) + st_size = (lltype.r_ulonglong(info.c_nFileSizeHigh) << 32) + st_size += info.c_nFileSizeLow + ctime, ctime_ns = FILE_TIME_to_time_t_nsec(info.c_ftCreationTime) + mtime, mtime_ns = FILE_TIME_to_time_t_nsec(info.c_ftLastWriteTime) + atime, atime_ns = FILE_TIME_to_time_t_nsec(info.c_ftLastAccessTime) + + result = (st_mode, + 0, 0, 0, 0, 0, + st_size, + atime, mtime, ctime) + + return make_stat_result(result) + + def by_handle_info_to_stat(info): + # similar to the one above + st_mode = attributes_to_mode(info.c_dwFileAttributes) + st_size = (lltype.r_ulonglong(info.c_nFileSizeHigh) << 32) + st_size += info.c_nFileSizeLow + ctime, ctime_ns = FILE_TIME_to_time_t_nsec(info.c_ftCreationTime) + mtime, mtime_ns = FILE_TIME_to_time_t_nsec(info.c_ftLastWriteTime) + atime, atime_ns = FILE_TIME_to_time_t_nsec(info.c_ftLastAccessTime) + + # specific to fstat() + st_ino = (lltype.r_ulonglong(info.c_nFileIndexHigh) << 32) + info.c_nFileIndexLow + st_nlink = info.c_nNumberOfLinks + + result = (st_mode, + st_ino, 0, st_nlink, 0, 0, + st_size, + atime, mtime, ctime) - def os_stat_llimpl(path): + return make_stat_result(result) + + def win32_stat_llimpl(path): data = lltype.malloc(WIN32_FILE_ATTRIBUTE_DATA, flavor='raw') try: l_path = rffi.str2charp(path) res = GetFileAttributesEx(l_path, GetFileExInfoStandard, data) rffi.free_charp(l_path) if res == 0: - # ignore the GetLastError() which is a number that we cannot - # easily report... - XXX - YYY + raise WindowsError(rwin32.GetLastError(), "os_stat failed") + return attribute_data_to_stat(data) finally: lltype.free(data, flavor='raw') + win32_lstat_llimpl = win32_stat_llimpl + + def win32_fstat_llimpl(fd): + info = lltype.malloc(BY_HANDLE_FILE_INFORMATION, flavor='raw') + try: + handle = rwin32._get_osfhandle(fd) + res = GetFileInformationByHandle(handle, info) + if res == 0: + raise WindowsError(rwin32.GetLastError(), "os_fstat failed") + return by_handle_info_to_stat(info) + finally: + lltype.free(info, flavor='raw') + Modified: pypy/trunk/pypy/rpython/module/test/test_ll_os_path.py ============================================================================== --- pypy/trunk/pypy/rpython/module/test/test_ll_os_path.py (original) +++ pypy/trunk/pypy/rpython/module/test/test_ll_os_path.py Fri Feb 20 17:03:05 2009 @@ -1,6 +1,6 @@ import py -import os +import sys, os from pypy.tool.pytest.modcheck import skipimporterror skipimporterror("ctypes") @@ -33,7 +33,9 @@ interpret(f, []) def test_isdir(): - import py; py.test.skip("XXX cannot run os.stat() on the llinterp yet") + if sys.platform != 'win32': + py.test.skip("XXX cannot run os.stat() on the llinterp yet") + s = str(udir.join('test_isdir')) def f(): return os.path.isdir(s) @@ -42,3 +44,13 @@ os.mkdir(s) res = interpret(f, []) assert res is True + + # On Windows, the libc stat() is flawed: + # stat('c:/temp') works + # but stat('c:/temp/') does not find the directory... + # This test passes with our own stat() implementation. + s += os.path.sep + def f(): + return os.path.isdir(s) + res = interpret(f, []) + assert res is True From afa at codespeak.net Fri Feb 20 18:32:32 2009 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 20 Feb 2009 18:32:32 +0100 (CET) Subject: [pypy-svn] r62054 - pypy/trunk/pypy/rpython/module Message-ID: <20090220173232.26F11169E7A@codespeak.net> Author: afa Date: Fri Feb 20 18:32:31 2009 New Revision: 62054 Modified: pypy/trunk/pypy/rpython/module/ll_time.py Log: Fix intermittent failures in test_ll_time on windows: ftime does exist, and needed for time.time() to return fractional times Modified: pypy/trunk/pypy/rpython/module/ll_time.py ============================================================================== --- pypy/trunk/pypy/rpython/module/ll_time.py (original) +++ pypy/trunk/pypy/rpython/module/ll_time.py Fri Feb 20 18:32:31 2009 @@ -11,10 +11,14 @@ from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo -if sys.platform.startswith('win'): - includes = ['time.h', 'windows.h'] +if sys.platform == 'win32': + TIME_H = 'time.h' + FTIME = '_ftime64' + includes = [TIME_H, 'windows.h', 'sys/timeb.h'] else: - includes = ['sys/time.h', 'time.h', 'errno.h', 'sys/select.h', + TIME_H = 'sys/time.h' + FTIME = 'ftime' + includes = [TIME_H, 'time.h', 'errno.h', 'sys/select.h', 'sys/types.h', 'unistd.h', 'sys/timeb.h'] @@ -26,7 +30,7 @@ TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), ('tv_usec', rffi.INT)]) HAVE_GETTIMEOFDAY = platform.Has('gettimeofday') - HAVE_FTIME = platform.Has('ftime') + HAVE_FTIME = platform.Has(FTIME) if sys.platform == 'freebsd7': @@ -36,7 +40,7 @@ class CConfigForFTime: _compilation_info_ = ExternalCompilationInfo( - includes=['sys/time.h', 'sys/timeb.h'], + includes=[TIME_H, 'sys/timeb.h'], libraries=libraries ) TIMEB = platform.Struct('struct timeb', [('time', rffi.INT), @@ -80,7 +84,7 @@ if self.HAVE_FTIME: self.configure(CConfigForFTime) - c_ftime = self.llexternal('ftime', [lltype.Ptr(self.TIMEB)], + c_ftime = self.llexternal(FTIME, [lltype.Ptr(self.TIMEB)], lltype.Void, _nowrapper=True, threadsafe=False) else: From fijal at codespeak.net Sat Feb 21 09:30:25 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 21 Feb 2009 09:30:25 +0100 (CET) Subject: [pypy-svn] r62071 - in pypy/branch/pyjitpl5/pypy/rpython: . lltypesystem lltypesystem/test Message-ID: <20090221083025.A27D71684D1@codespeak.net> Author: fijal Date: Sat Feb 21 09:30:23 2009 New Revision: 62071 Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/branch/pyjitpl5/pypy/rpython/rtyper.py Log: Port manually changes from the oo-jit branch. One test of ll2ctypes still fails, no clue why :( Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Sat Feb 21 09:30:23 2009 @@ -42,6 +42,8 @@ class LLInterpreter(object): """ low level interpreter working with concrete values. """ + current_interpreter = None + def __init__(self, typer, tracing=True, exc_data_ptr=None, malloc_check=True): self.bindings = {} @@ -66,6 +68,8 @@ retval = None self.traceback_frames = [] old_frame_stack = self.frame_stack[:] + prev_interpreter = LLInterpreter.current_interpreter + LLInterpreter.current_interpreter = self try: try: retval = llframe.eval() @@ -88,6 +92,7 @@ self.tracer.dump(line + '\n') raise finally: + LLInterpreter.current_interpreter = prev_interpreter assert old_frame_stack == self.frame_stack if self.tracer: if retval is not None: Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Sat Feb 21 09:30:23 2009 @@ -7,13 +7,18 @@ ctypes = None import os +from pypy import conftest from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.extfunc import ExtRegistryEntry -from pypy.rlib.objectmodel import Symbolic +from pypy.rlib.objectmodel import Symbolic, ComputedIntSymbolic from pypy.tool.uid import fixid from pypy.tool.tls import tlsobject from pypy.rlib.rarithmetic import r_uint, r_singlefloat from pypy.annotation import model as annmodel +from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython.lltypesystem.rclass import OBJECT +from pypy.rpython.annlowlevel import base_ptr_lltype +from pypy.rpython import raddress def uaddressof(obj): return fixid(ctypes.addressof(obj)) @@ -41,6 +46,9 @@ rffi.LONGLONG: ctypes.c_longlong, rffi.ULONGLONG: ctypes.c_ulonglong, rffi.SIZE_T: ctypes.c_size_t, + lltype.Bool: ctypes.c_long, # XXX + llmemory.Address: ctypes.c_void_p, + llmemory.GCREF: ctypes.c_void_p, }) # for unicode strings, do not use ctypes.c_wchar because ctypes @@ -173,7 +181,8 @@ def build_new_ctypes_type(T, delayed_builders): if isinstance(T, lltype.Ptr): if isinstance(T.TO, lltype.FuncType): - argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS] + argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS + if ARG is not lltype.Void] if T.TO.RESULT is lltype.Void: restype = None else: @@ -181,11 +190,15 @@ return ctypes.CFUNCTYPE(restype, *argtypes) else: return ctypes.POINTER(get_ctypes_type(T.TO, delayed_builders)) + elif T is lltype.Void: + return ctypes.c_long # opaque pointer elif isinstance(T, lltype.Struct): return build_ctypes_struct(T, delayed_builders) elif isinstance(T, lltype.Array): return build_ctypes_array(T, delayed_builders) elif isinstance(T, lltype.OpaqueType): + if T is lltype.RuntimeTypeInfo: + return ctypes.c_char * 2 if T.hints.get('external', None) != 'C': raise TypeError("%s is not external" % T) return ctypes.c_char * T.hints['getsize']() @@ -199,6 +212,39 @@ while delayed_builders: delayed_builders.pop()() +def remove_regular_struct_content(container): + STRUCT = container._TYPE + for field_name in STRUCT._names: + FIELDTYPE = getattr(STRUCT, field_name) + if not isinstance(FIELDTYPE, lltype.ContainerType): + delattr(container, field_name) + +def convert_array(container, carray=None): + ARRAY = container._TYPE + if carray is None: + # if 'container' is an inlined substructure, convert the whole + # bigger structure at once + parent, parentindex = lltype.parentlink(container) + if parent is not None: + convert_struct(parent) + return + # regular case: allocate a new ctypes array of the proper type + cls = get_ctypes_type(ARRAY) + carray = cls._malloc(container.getlength()) + add_storage(container, _array_mixin, carray) + if not isinstance(ARRAY.OF, lltype.ContainerType): + # fish that we have enough space + ctypes_array = ctypes.cast(carray.items, + ctypes.POINTER(carray.items._type_)) + for i in range(container.getlength()): + item_value = container.items[i] # fish fish + ctypes_array[i] = lltype2ctypes(item_value) + remove_regular_array_content(container) + else: + assert isinstance(ARRAY.OF, lltype.Struct) + for i in range(container.getlength()): + item_ptr = container.items[i] # fish fish + convert_struct(item_ptr, carray.items[i]) def convert_struct(container, cstruct=None): STRUCT = container._TYPE @@ -211,8 +257,8 @@ return # regular case: allocate a new ctypes Structure of the proper type cls = get_ctypes_type(STRUCT) - if STRUCT._arrayfld: - n = len(getattr(container, STRUCT._arrayfld).items) + if STRUCT._arrayfld is not None: + n = getattr(container, STRUCT._arrayfld).getlength() else: n = None cstruct = cls._malloc(n) @@ -222,45 +268,20 @@ field_value = getattr(container, field_name) if not isinstance(FIELDTYPE, lltype.ContainerType): # regular field - setattr(cstruct, field_name, lltype2ctypes(field_value)) + if FIELDTYPE != lltype.Void: + setattr(cstruct, field_name, lltype2ctypes(field_value)) else: # inlined substructure/subarray if isinstance(FIELDTYPE, lltype.Struct): csubstruct = getattr(cstruct, field_name) convert_struct(field_value, csubstruct) - else: + elif field_name == STRUCT._arrayfld: # inlined var-sized part csubarray = getattr(cstruct, field_name) convert_array(field_value, csubarray) - #raise NotImplementedError('inlined field', FIELDTYPE) + else: + raise NotImplementedError('inlined field', FIELDTYPE) remove_regular_struct_content(container) -def remove_regular_struct_content(container): - STRUCT = container._TYPE - for field_name in STRUCT._names: - FIELDTYPE = getattr(STRUCT, field_name) - if not isinstance(FIELDTYPE, lltype.ContainerType): - delattr(container, field_name) - -def convert_array(container, carray=None): - ARRAY = container._TYPE - cls = get_ctypes_type(ARRAY) - if carray is None: - carray = cls._malloc(container.getlength()) - add_storage(container, _array_mixin, carray) - if not isinstance(ARRAY.OF, lltype.ContainerType): - # fish that we have enough space - ctypes_array = ctypes.cast(carray.items, - ctypes.POINTER(carray.items._type_)) - for i in range(container.getlength()): - item_value = container.items[i] # fish fish - ctypes_array[i] = lltype2ctypes(item_value) - remove_regular_array_content(container) - else: - assert isinstance(ARRAY.OF, lltype.Struct) - for i in range(container.getlength()): - item_ptr = container.items[i] # fish fish - convert_struct(item_ptr, carray.items[i]) - def remove_regular_array_content(container): for i in range(container.getlength()): container.items[i] = None @@ -272,12 +293,18 @@ remove_regular_struct_content(container) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) - if isinstance(FIELDTYPE, lltype.Array): - convert_array(getattr(container, field_name), - getattr(ctypes_storage, field_name)) - elif isinstance(FIELDTYPE, lltype.ContainerType): - struct_use_ctypes_storage(getattr(container, field_name), - getattr(ctypes_storage, field_name)) + if isinstance(FIELDTYPE, lltype.ContainerType): + if isinstance(FIELDTYPE, lltype.Struct): + struct_use_ctypes_storage(getattr(container, field_name), + getattr(ctypes_storage, field_name)) + elif isinstance(FIELDTYPE, lltype.Array): + assert FIELDTYPE._hints.get('nolength', False) == False + arraycontainer = _array_of_known_length(FIELDTYPE) + arraycontainer._storage = getattr(ctypes_storage, field_name) + arraycontainer._setparentstructure(container, field_name) + object.__setattr__(container, field_name, arraycontainer) + else: + raise NotImplementedError(FIELDTYPE) # ____________________________________________________________ # Ctypes-aware subclasses of the _parentable classes @@ -343,6 +370,12 @@ def __ne__(self, other): return not (self == other) + def __hash__(self): + if self._storage is not None: + return ctypes.addressof(self._storage) + else: + return object.__hash__(self) + def __repr__(self): if self._storage is None: return '' % (self._TYPE,) @@ -406,6 +439,15 @@ items = property(getitems) +class _array_of_known_length(_array_of_unknown_length): + __slots__ = () + + def getlength(self): + return self._storage.length + + def getbounds(self): + return 0, self.getlength() + # ____________________________________________________________ def _find_parent(llobj): @@ -423,12 +465,41 @@ ofs = getattr(c_tp, parentindex).offset return next_p, next_i + ofs +# ____________________________________________________________ # XXX THIS IS A HACK XXX # ctypes does not keep callback arguments alive. So we do. Forever # we need to think deeper how to approach this problem # additionally, this adds mess to __del__ "semantics" -_all_callbacks = [] +_all_callbacks = {} +_all_callbacks_results = [] +_callback2obj = {} + +# this is just another hack that passes around references to applevel types +# disguised as base_ptr_lltype +class Dummy(object): + pass + +_opaque_cache = {Dummy():0} +_opaque_list = [Dummy()] + +def new_opaque_object(llobj): + try: + return _opaque_cache[llobj] + except KeyError: + assert len(_opaque_cache) == len(_opaque_list) + ctypes_type = get_ctypes_type(base_ptr_lltype()) + val = ctypes.cast(len(_opaque_cache), ctypes_type) + _opaque_list.append(llobj) + _opaque_cache[llobj] = val + return val + +def get_rtyper(): + llinterp = LLInterpreter.current_interpreter + if llinterp is not None: + return llinterp.typer + else: + return None def lltype2ctypes(llobj, normalize=True): """Convert the lltype object 'llobj' to its ctypes equivalent. @@ -439,39 +510,91 @@ return uninitialized2ctypes(llobj.TYPE) T = lltype.typeOf(llobj) + if isinstance(T, lltype.Ptr): if not llobj: # NULL pointer return get_ctypes_type(T)() - container = llobj._obj + if T is base_ptr_lltype(): + return new_opaque_object(llobj) + if T == llmemory.GCREF: + if isinstance(llobj, _llgcref): + return ctypes.c_void_p(llobj.intval) + container = llobj._obj.container + T = lltype.Ptr(lltype.typeOf(container)) + # otherwise it came from integer and we want a c_void_p with + # the same valu + else: + container = llobj._obj if isinstance(T.TO, lltype.FuncType): - if not hasattr(container, '_callable'): - raise NotImplementedError("ctypes wrapper for ll function " - "without a _callable") - else: - ctypes_func_type = get_ctypes_type(T) - def callback(*cargs): - assert len(cargs) == len(T.TO.ARGS) - llargs = [ctypes2lltype(ARG, cargs) - for ARG, cargs in zip(T.TO.ARGS, cargs)] - llres = container._callable(*llargs) - assert lltype.typeOf(llres) == T.TO.RESULT - if T.TO.RESULT is lltype.Void: - return None + # XXX a temporary workaround for comparison of lltype.FuncType + key = llobj._obj.__dict__.copy() + key['_TYPE'] = repr(key['_TYPE']) + items = key.items() + items.sort() + key = tuple(items) + if key in _all_callbacks: + return _all_callbacks[key] + v1voidlist = [(i, getattr(container, '_void' + str(i), None)) + for i in range(len(T.TO.ARGS)) + if T.TO.ARGS[i] is lltype.Void] + def callback(*cargs): + cargs = list(cargs) + for v1 in v1voidlist: + cargs.insert(v1[0], v1[1]) + assert len(cargs) == len(T.TO.ARGS) + llargs = [] + for ARG, carg in zip(T.TO.ARGS, cargs): + if ARG is lltype.Void: + llargs.append(carg) else: - return lltype2ctypes(llres) - res = ctypes_func_type(callback) - _all_callbacks.append(res) + llargs.append(ctypes2lltype(ARG, carg)) + if hasattr(container, 'graph'): + if LLInterpreter.current_interpreter is None: + raise AssertionError + llinterp = LLInterpreter.current_interpreter + llres = llinterp.eval_graph(container.graph, llargs) + else: + llres = container._callable(*llargs) + assert lltype.typeOf(llres) == T.TO.RESULT + if T.TO.RESULT is lltype.Void: + return None + res = lltype2ctypes(llres) + if isinstance(T.TO.RESULT, lltype.Ptr): + _all_callbacks_results.append(res) + res = ctypes.cast(res, ctypes.c_void_p).value + if res is None: + return 0 return res - if T.TO._gckind != 'raw' and not T.TO._hints.get('callback', None): - raise Exception("can only pass 'raw' data structures to C, not %r" - % (T.TO._gckind,)) + if conftest.option.usepdb: + callback_original = callback + def callback(*cargs): + try: + return callback_original(*cargs) + except: + import pdb, sys; pdb.post_mortem(sys.exc_traceback) + raise + + if isinstance(T.TO.RESULT, lltype.Ptr): + TMod = lltype.Ptr(lltype.FuncType(T.TO.ARGS, + lltype.Signed)) + ctypes_func_type = get_ctypes_type(TMod) + res = ctypes_func_type(callback) + ctypes_func_type = get_ctypes_type(T) + res = ctypes.cast(res, ctypes_func_type) + else: + ctypes_func_type = get_ctypes_type(T) + res = ctypes_func_type(callback) + _callback2obj[ctypes.cast(res, ctypes.c_void_p).value] = container + _all_callbacks[key] = res + return res index = 0 if isinstance(container, lltype._subarray): topmost, index = _find_parent(container) container = topmost + if container._storage is None: raise RuntimeError("attempting to pass a freed structure to C") if container._storage is True: @@ -481,7 +604,10 @@ elif isinstance(T.TO, lltype.Array): convert_array(container) elif isinstance(T.TO, lltype.OpaqueType): - cbuf = ctypes.create_string_buffer(T.TO.hints['getsize']()) + if T.TO != lltype.RuntimeTypeInfo: + cbuf = ctypes.create_string_buffer(T.TO.hints['getsize']()) + else: + cbuf = ctypes.create_string_buffer("\x00") add_storage(container, _parentable_mixin, cbuf) else: raise NotImplementedError(T) @@ -505,6 +631,8 @@ if isinstance(llobj, Symbolic): if isinstance(llobj, llmemory.ItemOffset): llobj = ctypes.sizeof(get_ctypes_type(llobj.TYPE)) * llobj.repeat + elif isinstance(llobj, ComputedIntSymbolic): + llobj = llobj.compute_fn() else: raise NotImplementedError(llobj) # don't know about symbolic value @@ -513,6 +641,7 @@ if T is lltype.SingleFloat: return ctypes.c_float(float(llobj)) + return llobj def ctypes2lltype(T, cobj): @@ -522,11 +651,24 @@ if isinstance(T, lltype.Ptr): if not cobj: # NULL pointer return lltype.nullptr(T.TO) + if T is base_ptr_lltype(): + return _opaque_list[ctypes.cast(cobj, ctypes.c_void_p).value] if isinstance(T.TO, lltype.Struct): if T.TO._arrayfld is not None: - lgt = getattr(cobj.contents, T.TO._arrayfld).length - container = lltype._struct(T.TO, lgt) + carray = getattr(cobj.contents, T.TO._arrayfld) + container = lltype._struct(T.TO, carray.length) else: + # special treatment of 'OBJECT' subclasses + if get_rtyper() and lltype._castdepth(T.TO, OBJECT) > 0: + ctypes_object = get_ctypes_type(lltype.Ptr(OBJECT)) + as_obj = ctypes2lltype(lltype.Ptr(OBJECT), + ctypes.cast(cobj, ctypes_object)) + TObj = get_rtyper().get_type_for_typeptr(as_obj.typeptr) + if TObj != T.TO: + ctypes_instance = get_ctypes_type(lltype.Ptr(TObj)) + return lltype.cast_pointer(T, + ctypes2lltype(lltype.Ptr(TObj), + ctypes.cast(cobj, ctypes_instance))) container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) elif isinstance(T.TO, lltype.Array): @@ -534,16 +676,30 @@ container = _array_of_unknown_length(T.TO) container._storage = cobj.contents else: - raise NotImplementedError("array with an explicit length") + container = _array_of_known_length(T.TO) + container._storage = cobj.contents elif isinstance(T.TO, lltype.FuncType): - _callable = get_ctypes_trampoline(T.TO, cobj) - return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), - _callable=_callable) + cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value + if cobjkey in _callback2obj: + container = _callback2obj[cobjkey] + else: + _callable = get_ctypes_trampoline(T.TO, cobj) + return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'), + _callable=_callable) elif isinstance(T.TO, lltype.OpaqueType): - container = lltype._opaque(T.TO) + if T == llmemory.GCREF: + # XXX obscure hack + return _llgcref(cobj) + else: + container = lltype._opaque(T.TO) else: raise NotImplementedError(T) llobj = lltype._ptr(T, container, solid=True) + elif T is llmemory.Address: + if cobj is None: + llobj = llmemory.NULL + else: + llobj = _lladdress(cobj) elif T is lltype.Char: llobj = chr(cobj) elif T is lltype.UniChar: @@ -554,6 +710,8 @@ if isinstance(cobj, ctypes.c_float): cobj = cobj.value llobj = r_singlefloat(cobj) + elif T is lltype.Void: + llobj = cobj else: from pypy.rpython.lltypesystem import rffi try: @@ -669,7 +827,8 @@ funcname, place)) # get_ctypes_type() can raise NotImplementedError too - cfunc.argtypes = [get_ctypes_type(T) for T in FUNCTYPE.ARGS] + cfunc.argtypes = [get_ctypes_type(T) for T in FUNCTYPE.ARGS + if not T is lltype.Void] if FUNCTYPE.RESULT is lltype.Void: cfunc.restype = None else: @@ -699,10 +858,18 @@ for i in range(len(FUNCTYPE.ARGS)): if isinstance(FUNCTYPE.ARGS[i], lltype.ContainerType): container_arguments.append(i) + void_arguments = [] + for i in range(len(FUNCTYPE.ARGS)): + if FUNCTYPE.ARGS[i] is lltype.Void: + void_arguments.append(i) def invoke_via_ctypes(*argvalues): - cargs = [lltype2ctypes(value) for value in argvalues] - for i in container_arguments: - cargs[i] = cargs[i].contents + cargs = [] + for i in range(len(FUNCTYPE.ARGS)): + if i not in void_arguments: + cvalue = lltype2ctypes(argvalues[i]) + if i in container_arguments: + cvalue = cvalue.contents + cargs.append(cvalue) _restore_c_errno() cres = cfunc(*cargs) _save_c_errno() @@ -750,12 +917,14 @@ return annmodel.lltype_to_annotation(RESTYPE) def specialize_call(self, hop): + from pypy.rpython.rbuiltin import gen_cast hop.exception_cannot_occur() s_RESTYPE = hop.args_s[0] assert s_RESTYPE.is_constant() RESTYPE = s_RESTYPE.const v_arg = hop.inputarg(hop.args_r[1], arg=1) - return hop.genop('force_cast', [v_arg], resulttype = RESTYPE) + TYPE1 = v_arg.concretetype + return gen_cast(hop.llops, RESTYPE, v_arg) def typecheck_ptradd(T): # --- ptradd() is only for pointers to non-GC, no-length arrays. @@ -779,7 +948,7 @@ cptr = ctypes.cast(ctypes.c_void_p(addr), ctypes_arrayptr_type) return ctypes2lltype(T, cptr) -class ForceCastEntry(ExtRegistryEntry): +class ForcePtrAddEntry(ExtRegistryEntry): _about_ = force_ptradd def compute_result_annotation(self, s_ptr, s_n): @@ -794,6 +963,84 @@ return hop.genop('direct_ptradd', [v_ptr, v_n], resulttype = v_ptr.concretetype) +class _lladdress(long): + _TYPE = llmemory.Address + + def __new__(cls, void_p): + self = long.__new__(cls, void_p.value) + self.void_p = void_p + self.intval = void_p.value + if self.intval > sys.maxint: + self.intval = int(self.intval - 2*(sys.maxint + 1)) + return self + + def _cast_to_ptr(self, TP): + return force_cast(TP, self.intval) + + def __repr__(self): + return '<_lladdress %s>' % (self.void_p,) + + def __eq__(self, other): + return cast_adr_to_int(other) == self.intval + + def __ne__(self, other): + return not self == other + +class _llgcref(object): + _TYPE = llmemory.GCREF + + def __init__(self, void_p): + self.intval = void_p.value + + def __eq__(self, other): + if isinstance(other, _llgcref): + return self.intval == other.intval + return force_cast(lltype.Signed, other) == self.intval + + def __ne__(self, other): + return not self == other + + def __nonzero__(self): + return bool(self.intval) + + def _cast_to_ptr(self, PTRTYPE): + return force_cast(PTRTYPE, self.intval) + + def _cast_to_int(self): + return self.intval + + def _cast_to_adr(self): + return _lladdress(ctypes.c_void_p(self.intval)) + +def cast_adr_to_int(addr): + if isinstance(addr, llmemory.fakeaddress): + # use ll2ctypes to obtain a real ctypes-based representation of + # the memory, and cast that address as an integer + if addr.ptr is None: + res = 0 + else: + res = force_cast(lltype.Signed, addr.ptr) + else: + res = addr._cast_to_int() + if res > sys.maxint: + res = res - 2*(sys.maxint + 1) + assert int(res) == res + return int(res) + return res + +class CastAdrToIntEntry(ExtRegistryEntry): + _about_ = cast_adr_to_int + + def compute_result_annotation(self, s_addr): + return annmodel.SomeInteger() + + def specialize_call(self, hop): + assert isinstance(hop.args_r[0], raddress.AddressRepr) + adr, = hop.inputargs(hop.args_r[0]) + hop.exception_cannot_occur() + return hop.genop('cast_adr_to_int', [adr], + resulttype = lltype.Signed) + # ____________________________________________________________ # errno Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py Sat Feb 21 09:30:23 2009 @@ -798,6 +798,8 @@ "%s to %s" % (CURTYPE, PTRTYPE)) if (isinstance(CURTYPE.TO, OpaqueType) and not isinstance(PTRTYPE.TO, OpaqueType)): + if hasattr(ptr, '_cast_to_ptr'): + return ptr._cast_to_ptr(PTRTYPE) if not ptr: return nullptr(PTRTYPE.TO) try: @@ -809,6 +811,8 @@ return cast_pointer(PTRTYPE, p) elif (not isinstance(CURTYPE.TO, OpaqueType) and isinstance(PTRTYPE.TO, OpaqueType)): + if hasattr(ptr, '_cast_to_opaque'): + return ptr._cast_to_opaque(PTRTYPE) if not ptr: return nullptr(PTRTYPE.TO) return opaqueptr(PTRTYPE.TO, 'hidden', container = ptr._obj, @@ -1085,12 +1089,20 @@ if isinstance(self._T, FuncType): if len(args) != len(self._T.ARGS): raise TypeError,"calling %r with wrong argument number: %r" % (self._T, args) - for a, ARG in zip(args, self._T.ARGS): + for i, a, ARG in zip(range(len(self._T.ARGS)), args, self._T.ARGS): if typeOf(a) != ARG: + # ARG could be Void + if ARG == Void: + try: + value = getattr(self._obj, '_void' + str(i)) + except AttributeError: + pass + else: + assert a == value # special case: ARG can be a container type, in which # case a should be a pointer to it. This must also be # special-cased in the backends. - if not (isinstance(ARG, ContainerType) + elif not (isinstance(ARG, ContainerType) and typeOf(a) == Ptr(ARG)): args_repr = [typeOf(arg) for arg in args] raise TypeError, ("calling %r with wrong argument " Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py Sat Feb 21 09:30:23 2009 @@ -386,7 +386,7 @@ ll_runtime_type_info, OBJECT, destrptr) vtable = self.rclass.getvtable() - #self.rtyper.type_for_typeptr[vtable._obj] = self.lowleveltype.TO + self.rtyper.type_for_typeptr[vtable._obj] = self.lowleveltype.TO def common_repr(self): # -> object or nongcobject reprs return getinstancerepr(self.rtyper, None, self.gcflavor) Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Sat Feb 21 09:30:23 2009 @@ -7,11 +7,14 @@ from pypy.rpython.lltypesystem.ll2ctypes import standard_c_lib from pypy.rpython.lltypesystem.ll2ctypes import uninitialized2ctypes from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED, force_cast +from pypy.rpython.lltypesystem.ll2ctypes import cast_adr_to_int, get_ctypes_type from pypy.rpython.annlowlevel import llhelper from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.tool.udir import udir from pypy.rpython.test.test_llinterp import interpret +from pypy.annotation.annrpython import RPythonAnnotator +from pypy.rpython.rtyper import RPythonTyper class TestLL2Ctypes(object): @@ -826,13 +829,152 @@ c1 = lltype2ctypes(a1) c2 = lltype2ctypes(a2) assert type(c1) is type(c2) + lltype.free(a1, flavor='raw') + lltype.free(a2, flavor='raw') + assert not ALLOCATED # detects memory leaks in the test + + def test_varsized_struct(self): + S = lltype.Struct('S', ('x', lltype.Signed), + ('a', lltype.Array(lltype.Char))) + s1 = lltype.malloc(S, 6, flavor='raw') + s1.x = 5 + s1.a[2] = 'F' + sc = lltype2ctypes(s1, normalize=False) + assert isinstance(sc.contents, ctypes.Structure) + assert sc.contents.x == 5 + assert sc.contents.a.length == 6 + assert sc.contents.a.items[2] == ord('F') + sc.contents.a.items[3] = ord('P') + assert s1.a[3] == 'P' + s1.a[1] = 'y' + assert sc.contents.a.items[1] == ord('y') + # now go back to lltype... + res = ctypes2lltype(lltype.Ptr(S), sc) + assert res == s1 + assert res.x == 5 + assert len(res.a) == 6 + lltype.free(s1, flavor='raw') + assert not ALLOCATED # detects memory leaks in the test + + def test_with_explicit_length(self): + A = lltype.Array(lltype.Signed) + a1 = lltype.malloc(A, 5, flavor='raw') + a1[0] = 42 + c1 = lltype2ctypes(a1, normalize=False) + assert c1.contents.length == 5 + assert c1.contents.items[0] == 42 + res = ctypes2lltype(lltype.Ptr(A), c1) + assert res == a1 + assert len(res) == 5 + assert res[0] == 42 + res[0] += 1 + assert c1.contents.items[0] == 43 + assert a1[0] == 43 + a1[0] += 2 + assert c1.contents.items[0] == 45 + assert a1[0] == 45 + c1.contents.items[0] += 3 + assert res[0] == 48 + assert a1[0] == 48 + lltype.free(a1, flavor='raw') + assert not ALLOCATED # detects memory leaks in the test + + def test_c_callback_with_void_arg_2(self): + ftest = [] + def f(x): + ftest.append(x) + F = lltype.FuncType([lltype.Void], lltype.Void) + fn = lltype.functionptr(F, 'askjh', _callable=f, _void0=-5) + fn(-5) + assert ftest == [-5] + fn2 = lltype2ctypes(fn) + fn2() + assert ftest == [-5, -5] + fn3 = ctypes2lltype(lltype.Ptr(F), fn2) + fn3(-5) + assert ftest == [-5, -5, -5] + + def test_c_callback_with_void_arg_3(self): + import pypy + def f(i): + x = 'X' * i + return x[-2] + a = RPythonAnnotator() + r = a.build_types(f, [int]) + rtyper = RPythonTyper(a) + rtyper.specialize() + a.translator.rtyper = rtyper + graph = a.translator.graphs[0] + op = graph.startblock.operations[-1] + assert op.opname == 'direct_call' + assert op.args[0].value._obj._callable == pypy.rpython.lltypesystem.rstr.LLHelpers.ll_stritem.im_func + assert op.args[1].value == pypy.rpython.lltypesystem.rstr.LLHelpers + assert op.args[3].value == -2 + + def test_pass_around_t_object(self): + from pypy.rpython.annlowlevel import base_ptr_lltype + T = base_ptr_lltype() + + class X(object): + _TYPE = T + x = 10 + + def callback(x): + return x.x + + c_source = py.code.Source(""" + int eating_callback(void *arg, int(*call)(int)) + { + return call(arg); + } + """) + + eci = ExternalCompilationInfo(separate_module_sources=[c_source]) + + args = [T, rffi.CCallback([T], rffi.INT)] + eating_callback = rffi.llexternal('eating_callback', args, rffi.INT, + compilation_info=eci) + + res = eating_callback(X(), callback) + assert res == 10 - def test_varsized_struct(self): - STR = lltype.Struct('rpy_string', ('hash', lltype.Signed), - ('chars', lltype.Array(lltype.Char, hints={'immutable': True}))) - s = lltype.malloc(STR, 3, flavor='raw') - one = force_cast(rffi.VOIDP, s) - # sanity check - #assert lltype2ctypes(one).contents.items._length_ > 0 - two = force_cast(lltype.Ptr(STR), one) - assert s == two + def test_recursive_struct_more(self): + NODE = lltype.ForwardReference() + NODE.become(lltype.Struct('NODE', ('value', lltype.Signed), + ('next', lltype.Ptr(NODE)))) + CNODEPTR = get_ctypes_type(NODE) + pc = CNODEPTR() + pc.value = 42 + pc.next = ctypes.pointer(pc) + p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc)) + assert p.value == 42 + assert p.next == p + pc2 = lltype2ctypes(p) + assert pc2.contents.value == 42 + assert pc2.contents.next.contents.value == 42 + + def test_cast_adr_to_int(self): + class someaddr(object): + def _cast_to_int(self): + return sys.maxint/2 * 3 + + res = cast_adr_to_int(someaddr()) + assert isinstance(res, int) + assert res == -sys.maxint/2 - 3 + + def test_cast_gcref_back_and_forth(self): + NODE = lltype.GcStruct('NODE') + node = lltype.malloc(NODE) + ref = lltype.cast_opaque_ptr(llmemory.GCREF, node) + back = rffi.cast(llmemory.GCREF, rffi.cast(lltype.Signed, ref)) + assert lltype.cast_opaque_ptr(lltype.Ptr(NODE), ref) == node + + def test_gcref_forth_and_back(self): + cp = ctypes.c_void_p(1234) + v = ctypes2lltype(llmemory.GCREF, cp) + assert lltype2ctypes(v).value == cp.value + v1 = ctypes2lltype(llmemory.GCREF, cp) + assert v == v1 + assert v + v2 = ctypes2lltype(llmemory.GCREF, ctypes.c_void_p(1235)) + assert v2 != v Modified: pypy/branch/pyjitpl5/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rtyper.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rtyper.py Sat Feb 21 09:30:23 2009 @@ -57,6 +57,7 @@ self._dict_traits = {} self.class_reprs = {} self.instance_reprs = {} + self.type_for_typeptr = {} self.pbc_reprs = {} self.classes_with_wrapper = {} self.wrapper_context = None # or add an extra arg to convertvar? @@ -131,6 +132,23 @@ result[repr.lowleveltype] = classdef return result + def lltype_to_vtable_mapping(self): + result = {} + for repr in self.instance_reprs.itervalues(): + result[repr.lowleveltype.TO] = repr.rclass.getvtable() + return result + + def get_type_for_typeptr(self, typeptr): + try: + return self.type_for_typeptr[typeptr._obj] + except KeyError: + # rehash the dictionary + type_for_typeptr = {} + for key, value in self.type_for_typeptr.items(): + type_for_typeptr[key] = value + self.type_for_typeptr = type_for_typeptr + return self.type_for_typeptr[typeptr._obj] + def makekey(self, s_obj): return pair(self.type_system, s_obj).rtyper_makekey(self) From fijal at codespeak.net Sat Feb 21 09:32:19 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 21 Feb 2009 09:32:19 +0100 (CET) Subject: [pypy-svn] r62072 - in pypy/branch/pyjitpl5/pypy/jit: backend backend/x86 backend/x86/test metainterp metainterp/test Message-ID: <20090221083219.2C6101684D1@codespeak.net> Author: fijal Date: Sat Feb 21 09:32:18 2009 New Revision: 62072 Added: pypy/branch/pyjitpl5/pypy/jit/backend/hlinfo.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py (contents, props changed) pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_loop_spec.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: A bit of progress for x86 backend. Some tests pass, but still they mostly fail. A hack in warmspot to be able to always return ints from the backend, might need a fix for typefor(). Port remainings of codebuf from oo-jit branch Added: pypy/branch/pyjitpl5/pypy/jit/backend/hlinfo.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/hlinfo.py Sat Feb 21 09:32:18 2009 @@ -0,0 +1,10 @@ + +class HighLevelJITInfo: + """ + A singleton class for the RPython-level JITed program to push information + that the backend can use or log. + """ + sys_executable = None + + +highleveljitinfo = HighLevelJITInfo() Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Sat Feb 21 09:32:18 2009 @@ -1,17 +1,17 @@ import sys import ctypes -from pypy.jit.backend.x86.ri386 import * -from codegen386 import symbolic -from history import Const, ConstInt, Box, MergePoint +from pypy.jit.backend.x86 import symbolic +from pypy.jit.metainterp.history import Const, ConstInt, Box, MergePoint from pypy.rpython.lltypesystem import lltype, rffi, ll2ctypes, rstr from pypy.rpython.lltypesystem.rclass import OBJECT from pypy.annotation import model as annmodel from pypy.tool.uid import fixid -from codegen386.regalloc import RegAlloc, FRAMESIZE, WORD, REGS -from codegen386.regalloc import arg_pos, lower_byte, stack_pos, Perform +from pypy.jit.backend.x86.regalloc import (RegAlloc, FRAMESIZE, WORD, REGS, + arg_pos, lower_byte, stack_pos, Perform) from pypy.rlib.objectmodel import we_are_translated, specialize from pypy.jit.backend.x86 import codebuf -from pypy.jit.backend.x86.rgenop import gc_malloc_fnaddr +from pypy.jit.backend.x86.support import gc_malloc_fnaddr +from pypy.jit.backend.x86.ri386 import * # our calling convention - we pass three first args as edx, ecx and eax # and the rest stays on stack @@ -55,7 +55,6 @@ ptr = rffi.cast(TP, guard_op._jmp_from - WORD) ptr[0] = new_rel_addr self.mc.redone(guard_op._jmp_from - WORD, guard_op._jmp_from) - self.most_recent_mp = guard_op.most_recent_mp if self.verbose and not we_are_translated(): import pprint print @@ -274,7 +273,11 @@ loc_size = arglocs[0] self.call(self.malloc_func_addr, [loc_size], eax) - def genop_getfield_gc__4(self, op, arglocs, resloc): + def genop_newstr(self, op, arglocs, result_loc): + loc_size = arglocs[0] + self.call(self.malloc_func_addr, [loc_size], eax) + + def genop_getfield_gc(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs #if isinstance(op.args[0], Constant): # x, _ = self.cpu.get_value_as_int(op.args[0].value) @@ -283,17 +286,19 @@ # ... self.mc.MOV(resloc, addr_add(base_loc, ofs_loc)) - genop_getfield_gc_ptr = genop_getfield_gc__4 - genop_getfield_raw__4 = genop_getfield_gc__4 - genop_getfield_raw_ptr = genop_getfield_gc__4 + genop_getfield_raw = genop_getfield_gc - def genop_setfield_gc__4(self, op, arglocs): + def genop_setfield_gc(self, op, arglocs): base_loc, ofs_loc, value_loc = arglocs self.mc.MOV(addr_add(base_loc, ofs_loc), value_loc) - genop_setfield_gc_ptr = genop_setfield_gc__4 - genop_setfield_raw__4 = genop_setfield_gc__4 - genop_setfield_raw_ptr = genop_setfield_gc__4 + def genop_strsetitem(self, op, arglocs): + base_loc, ofs_loc, val_loc = arglocs + basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR) + self.mc.MOV(addr8_add(base_loc, ofs_loc, basesize), + lower_byte(val_loc)) + + genop_setfield_raw = genop_setfield_gc def genop_strlen(self, op, arglocs, resloc): base_loc = arglocs[0] @@ -310,7 +315,6 @@ # position of the live values into a flat array of c_long's. # XXX update comment # we load constants into arguments - self.most_recent_mp = op op.position = self.mc.tell() op.comeback_bootstrap_addr = self.assemble_comeback_bootstrap(op) #nb_args = len(op.args) @@ -343,6 +347,9 @@ self.mc.TEST(loc, loc) self.implement_guard(op, self.mc.JZ, locs[1:]) + def genop_guard_no_exception(self, op, locs): + pass # XXX # exception handling + def genop_guard_false(self, op, locs): loc = locs[0] self.mc.TEST(loc, loc) @@ -404,18 +411,17 @@ @specialize.arg(2) def implement_guard(self, guard_op, emit_jump, locs): + # XXX add caching, as we need only one for each combination + # of locs recovery_addr = self.get_recovery_code(guard_op, locs) emit_jump(rel32(recovery_addr)) guard_op._jmp_from = self.mc.tell() def get_recovery_code(self, guard_op, locs): - guard_op.most_recent_mp = self.most_recent_mp index = self.cpu.make_guard_index(guard_op) recovery_code_addr = self.mc2.tell() - mp = self.most_recent_mp - assert len(mp.args) == len(locs) - # we need to copy arguments to our last merge point - stacklocs = mp.stacklocs + stacklocs = guard_op.stacklocs + assert len(locs) == len(stacklocs) for i in range(len(locs)): loc = locs[i] if isinstance(loc, REG): @@ -451,6 +457,7 @@ genop_call__4 = _new_gen_call() gen_call = _new_gen_call() genop_call_ptr = gen_call + genop_getitem = _new_gen_call() def genop_call_void(self, op, arglocs): extra_on_stack = 0 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/codebuf.py Sat Feb 21 09:32:18 2009 @@ -0,0 +1,172 @@ + +import os +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.jit.backend.x86.ri386 import I386CodeBuilder +from pypy.rlib.rmmap import PTR, alloc, free + +class CodeBlockOverflow(Exception): + pass + +class InMemoryCodeBuilder(I386CodeBuilder): + _last_dump_start = 0 + + def __init__(self, start, end): + map_size = end - start + data = rffi.cast(PTR, start) + self._init(data, map_size) + + def _init(self, data, map_size): + self._data = data + self._size = map_size + self._pos = 0 + + def write(self, data): + p = self._pos + if p + len(data) > self._size: + raise CodeBlockOverflow + for c in data: + self._data[p] = c + p += 1 + self._pos = p + + def tell(self): + baseaddr = rffi.cast(lltype.Signed, self._data) + return baseaddr + self._pos + + def seekback(self, count): + pos = self._pos - count + self._pos = pos + self._last_dump_start = pos + + def execute(self, arg1, arg2): + # XXX old testing stuff + fnptr = rffi.cast(lltype.Ptr(BINARYFN), self._data) + return fnptr(arg1, arg2) + + def done(self): + # normally, no special action is needed here + if machine_code_dumper.enabled: + machine_code_dumper.dump_range(self, self._last_dump_start, + self._pos) + self._last_dump_start = self._pos + + def redone(self, frm, to): + if machine_code_dumper.enabled: + baseaddr = rffi.cast(lltype.Signed, self._data) + machine_code_dumper.dump_range(self, frm - baseaddr, to - baseaddr) + + def log(self, msg): + if machine_code_dumper.enabled: + machine_code_dumper.dump(self, 'LOG', self._pos, msg) + + +BINARYFN = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed) + + +class MachineCodeDumper: + enabled = True + log_fd = -1 + sys_executable = None + + def _freeze_(self): + # reset the machine_code_dumper global instance to its default state + if self.log_fd >= 0: + os.close(self.log_fd) + self.__dict__.clear() + return False + + def open(self): + if self.log_fd < 0: + # check the environment for a file name + s = os.environ.get('PYPYJITLOG') + if not s: + self.enabled = False + return False + try: + flags = os.O_WRONLY|os.O_CREAT|os.O_TRUNC + self.log_fd = os.open(s, flags, 0666) + except OSError: + os.write(2, "could not create log file\n") + self.enabled = False + return False + # log the executable name + from pypy.jit.backend.hlinfo import highleveljitinfo + os.write(self.log_fd, 'BACKEND i386\n') + if highleveljitinfo.sys_executable: + os.write(self.log_fd, 'SYS_EXECUTABLE %s\n' % ( + highleveljitinfo.sys_executable,)) + return True + + def dump(self, cb, tag, pos, msg): + if not self.open(): + return + line = '%s @%x +%d %s\n' % (tag, cb.tell() - cb._pos, pos, msg) + os.write(self.log_fd, line) + + def dump_range(self, cb, start, end): + HEX = '0123456789ABCDEF' + dump = [] + for p in range(start, end): + o = ord(cb._data[p]) + dump.append(HEX[o >> 4]) + dump.append(HEX[o & 15]) + if (p & 3) == 3: + dump.append(':') + self.dump(cb, 'CODE_DUMP', start, ''.join(dump)) + +machine_code_dumper = MachineCodeDumper() + + +class MachineCodeBlock(InMemoryCodeBuilder): + + def __init__(self, map_size): + data = alloc(map_size) + self._init(data, map_size) + + def __del__(self): + free(self._data, self._size) + +# ____________________________________________________________ + +from pypy.rpython.lltypesystem import lltype + +BUF = lltype.GcArray(lltype.Char) + +class LLTypeMachineCodeBlock(I386CodeBuilder): + # for testing only + + class State: + pass + state = State() + state.base = 1 + + def __init__(self, map_size): + self._size = map_size + self._pos = 0 + self._base = LLTypeMachineCodeBlock.state.base + LLTypeMachineCodeBlock.state.base += map_size + + def write(self, data): + p = self._pos + if p + len(data) > self._size: + raise CodeBlockOverflow + self._pos += len(data) + return + + def tell(self): + return self._base + self._pos + + def seekback(self, count): + self._pos -= count + + def done(self): + pass + +class LLTypeInMemoryCodeBuilder(LLTypeMachineCodeBlock): + _last_dump_start = 0 + + def __init__(self, start, end): + self._size = end - start + self._pos = 0 + self._base = start + Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Sat Feb 21 09:32:18 2009 @@ -2,12 +2,13 @@ """ Register allocation scheme. The idea is as follows: """ -from history import Box, Const, ConstInt, ConstPtr, ResOperation, MergePoint,\ - ConstAddr +from pypy.jit.metainterp.history import (Box, Const, ConstInt, ConstPtr, + ResOperation, MergePoint, ConstAddr) from pypy.jit.backend.x86.ri386 import * -from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi +from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi, rstr from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable +from pypy.jit.backend.x86 import symbolic # esi edi and ebp can be added to this list, provided they're correctly # saved and restored @@ -100,33 +101,29 @@ else: loop_consts = self._compute_loop_consts(mp, jump) self.current_stack_depth = len(mp.args) - if guard_op: - self.most_recent_mp = guard_op.most_recent_mp - else: - self.most_recent_mp = None self.computed_ops = self.walk_operations(operations, loop_consts) assert not self.reg_bindings def _start_from_guard_op(self, guard_op, mp, jump): - most_recent_mp = guard_op.most_recent_mp rev_stack_binds = {} self.jump_reg_candidates = {} + j = 0 for i in range(len(mp.args)): arg = mp.args[i] - stackpos = most_recent_mp.stacklocs[i] - loc = most_recent_mp.arglocs[i] if not isinstance(arg, Const): + stackpos = guard_op.stacklocs[j] + loc = guard_op.locs[j] if isinstance(loc, REG): self.free_regs = [reg for reg in self.free_regs if reg is not loc] self.reg_bindings[arg] = loc self.dirty_stack[arg] = True self.stack_bindings[arg] = stack_pos(stackpos) rev_stack_binds[stackpos] = arg + j += 1 if jump.opname != 'jump': return {} for i in range(len(jump.args)): argloc = jump.jump_target.arglocs[i] - stackpos = jump.jump_target.stacklocs[i] jarg = jump.args[i] if isinstance(argloc, REG): self.jump_reg_candidates[jarg] = argloc @@ -137,8 +134,9 @@ # overlap. pass # we don't care that they occupy the same place else: - self.stack_bindings[jarg] = stack_pos(stackpos) - self.dirty_stack[jarg] = True + #self.dirty_stack[jarg] = True + # XXX ^^^^^^^^^ why? + self.stack_bindings[jarg] = stack_pos(i) return {} def _compute_loop_consts(self, mp, jump): @@ -198,7 +196,6 @@ # operations that is a "last-time-seen" longevity = {} start_live = {} - most_recent_mp_args = [] for v in operations[0].args: start_live[v] = 0 for i in range(len(operations)): @@ -208,11 +205,10 @@ for arg in op.args: if isinstance(arg, Box): longevity[arg] = (start_live[arg], i) - if op.opname == "merge_point" or op.opname == 'catch': - most_recent_mp_args = op.args - elif op.opname.startswith('guard_'): - for arg in most_recent_mp_args: - longevity[arg] = (start_live[arg], i) + if op.opname.startswith('guard_'): + for arg in op.liveboxes: + if isinstance(arg, Box): + longevity[arg] = (start_live[arg], i) self.longevity = longevity def try_allocate_reg(self, v, selected_reg=None): @@ -261,8 +257,17 @@ # this means we cannot have it in IMM, eh if selected_reg in self.free_regs: return selected_reg, [Load(v, convert_to_imm(v), selected_reg)] - # otherwise we need to do all dance etc - raise NotImplementedError # XXX needs tests + v_to_spill = self.pick_variable_to_spill(v, forbidden_vars, selected_reg) + if v_to_spill not in self.stack_bindings or v_to_spill in self.dirty_stack: + newloc = self.stack_loc(v_to_spill) + try: + del self.dirty_stack[v_to_spill] + except KeyError: + pass + ops = [Store(v_to_spill, selected_reg, newloc)] + else: + ops = [] + return selected_reg, ops+[Load(v, convert_to_imm(v), selected_reg)] return convert_to_imm(v), [] def force_allocate_reg(self, v, forbidden_vars, selected_reg=None): @@ -273,6 +278,9 @@ loc = self.try_allocate_reg(v, selected_reg) if loc: return loc, [] + return self._spill_var(v, forbidden_vars, selected_reg) + + def _spill_var(self, v, forbidden_vars, selected_reg): v_to_spill = self.pick_variable_to_spill(v, forbidden_vars, selected_reg) loc = self.reg_bindings[v_to_spill] del self.reg_bindings[v_to_spill] @@ -286,6 +294,17 @@ return loc, [Store(v_to_spill, loc, newloc)] return loc, [] + def _locs_from_liveboxes(self, guard_op): + stacklocs = [] + locs = [] + for arg in guard_op.liveboxes: + if isinstance(arg, Box): + stacklocs.append(self.stack_loc(arg).position) + locs.append(self.loc(arg)) + guard_op.stacklocs = stacklocs + guard_op.locs = locs + return locs + def stack_loc(self, v): try: res = self.stack_bindings[v] @@ -391,75 +410,71 @@ # XXX we can sort out here by longevity if we need something # more optimal ops = [PerformDiscard(op, [])] - if self.most_recent_mp is None: - locs = [None] * len(op.args) - for i in range(len(op.args)): - arg = op.args[i] - assert not isinstance(arg, Const) - reg = None - loc = stack_pos(i) - self.stack_bindings[arg] = loc - if arg not in self.loop_consts: - reg = self.try_allocate_reg(arg) - if reg: - locs[i] = reg - self.dirty_stack[arg] = True - else: - locs[i] = loc - # otherwise we have it saved on stack, so no worry - else: - locs = [] - for arg in op.args: - l = self.loc(arg) - if isinstance(l, REG): - self.dirty_stack[arg] = True - locs.append(l) - # possibly constants - op.stacklocs = [self.stack_loc(arg).position for arg in op.args] + locs = [None] * len(op.args) + for i in range(len(op.args)): + arg = op.args[i] + assert not isinstance(arg, Const) + reg = None + loc = stack_pos(i) + self.stack_bindings[arg] = loc + if arg not in self.loop_consts: + reg = self.try_allocate_reg(arg) + if reg: + locs[i] = reg + self.dirty_stack[arg] = True + else: + locs[i] = loc + # otherwise we have it saved on stack, so no worry op.arglocs = locs ops[-1].arglocs = op.arglocs - self.most_recent_mp = op + op.stacklocs = [i for i in range(len(op.args))] # XXX be a bit smarter and completely ignore such vars self.eventually_free_vars(op.args) return ops - consider_catch = consider_merge_point + def consider_catch(self, op): + locs = [] + for arg in op.args: + l = self.loc(arg) + if isinstance(l, REG): + self.dirty_stack[arg] = True + locs.append(l) + # possibly constants + op.arglocs = locs + op.stacklocs = [self.stack_loc(arg).position for arg in op.args] + self.eventually_free_vars(op.args) + return [PerformDiscard(op, [])] def consider_guard(self, op): loc, ops = self.make_sure_var_in_reg(op.args[0], []) - #if self.most_recent_mp is self.first_merge_point: - locs = [self.loc(arg) for arg in self.most_recent_mp.args] + locs = self._locs_from_liveboxes(op) self.eventually_free_var(op.args[0]) - self.eventually_free_vars(self.most_recent_mp.args) + self.eventually_free_vars(op.liveboxes) return ops + [PerformDiscard(op, [loc] + locs)] + def consider_guard_no_exception(self, op): + locs = self._locs_from_liveboxes(op) + self.eventually_free_vars(op.liveboxes) + return [PerformDiscard(op, locs)] + consider_guard_true = consider_guard consider_guard_false = consider_guard - consider_guard_nonzero = consider_guard - consider_guard_iszero = consider_guard - consider_guard_nonnull = consider_guard - consider_guard_isnull = consider_guard - - def consider_guard2(self, op): - loc1, ops1 = self.make_sure_var_in_reg(op.args[0], []) - loc2, ops2 = self.make_sure_var_in_reg(op.args[1], []) - locs = [self.loc(arg) for arg in self.most_recent_mp.args] - self.eventually_free_vars(op.args + self.most_recent_mp.args) - return ops1 + ops2 + [PerformDiscard(op, [loc1, loc2] + locs)] - - consider_guard_lt = consider_guard2 - consider_guard_le = consider_guard2 - consider_guard_eq = consider_guard2 - consider_guard_ne = consider_guard2 - consider_guard_gt = consider_guard2 - consider_guard_ge = consider_guard2 - consider_guard_is = consider_guard2 - consider_guard_isnot = consider_guard2 - - def consider_guard_pause(self, op): - locs = [self.loc(arg) for arg in self.most_recent_mp.args] - self.eventually_free_vars(self.most_recent_mp.args) - return [PerformDiscard(op, locs)] + + #def consider_guard2(self, op): + # loc1, ops1 = self.make_sure_var_in_reg(op.args[0], []) + # loc2, ops2 = self.make_sure_var_in_reg(op.args[1], []) + # locs = [self.loc(arg) for arg in op.liveboxes] + # self.eventually_free_vars(op.args + op.liveboxes) + # return ops1 + ops2 + [PerformDiscard(op, [loc1, loc2] + locs)] + + #consider_guard_lt = consider_guard2 + #consider_guard_le = consider_guard2 + #consider_guard_eq = consider_guard2 + #consider_guard_ne = consider_guard2 + #consider_guard_gt = consider_guard2 + #consider_guard_ge = consider_guard2 + #consider_guard_is = consider_guard2 + #consider_guard_isnot = consider_guard2 def consider_guard_value(self, op): x = self.loc(op.args[0]) @@ -468,15 +483,15 @@ else: ops = [] y = self.loc(op.args[1]) - locs = [self.loc(arg) for arg in self.most_recent_mp.args] - self.eventually_free_vars(self.most_recent_mp.args + op.args) + locs = self._locs_from_liveboxes(op) + self.eventually_free_vars(op.liveboxes + op.args) return ops + [PerformDiscard(op, [x, y] + locs)] def consider_guard_class(self, op): x, ops = self.make_sure_var_in_reg(op.args[0], [], imm_fine=False) y = self.loc(op.args[1]) - locs = [self.loc(arg) for arg in self.most_recent_mp.args] - self.eventually_free_vars(self.most_recent_mp.args + op.args) + locs = self._locs_from_liveboxes(op) + self.eventually_free_vars(op.liveboxes + op.args) return ops + [PerformDiscard(op, [x, y] + locs)] def consider_return(self, op): @@ -565,11 +580,11 @@ consider_int_ne = consider_compop consider_int_eq = consider_compop - def _call(self, op, arglocs): + def _call(self, op, arglocs, force_store=[]): ops = [] # we need to store all variables which are now in registers for v, reg in self.reg_bindings.items(): - if self.longevity[v][1] >= self.position: + if self.longevity[v][1] > self.position or v in force_store: ops.append(Store(v, reg, self.stack_loc(v))) try: del self.dirty_stack[v] @@ -577,7 +592,7 @@ pass self.reg_bindings = newcheckdict() if op.results: - self.reg_bindings[op.results[0]] = eax + self.reg_bindings = {op.results[0]: eax} self.free_regs = [reg for reg in REGS if reg is not eax] return ops + [Perform(op, arglocs, eax)] else: @@ -599,6 +614,19 @@ def consider_new_with_vtable(self, op): return self._call(op, [self.loc(arg) for arg in op.args]) + def consider_newstr(self, op): + ops = self._call(op, [self.loc(arg) for arg in op.args], + [op.args[0]]) + loc, ops1 = self.make_sure_var_in_reg(op.args[0], []) + assert self.loc(op.results[0]) == eax + # now we have to reload length to some reasonable place + # XXX hardcoded length offset + self.eventually_free_var(op.args[0]) + ofs = symbolic.get_field_token(rstr.STR, 'chars')[0] + res = ops + ops1 + [PerformDiscard(ResOperation('setfield_gc', [], []), + [eax, imm(ofs), loc])] + return res + def consider_oononnull(self, op): argloc = self.loc(op.args[0]) self.eventually_free_var(op.args[0]) @@ -606,7 +634,7 @@ assert reg return [Perform(op, [argloc], reg)] - def consider_setfield_gc__4(self, op): + def consider_setfield_gc(self, op): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) value_loc, ops2 = self.make_sure_var_in_reg(op.args[2], op.args) @@ -614,9 +642,10 @@ return (ops0 + ops1 + ops2 + [PerformDiscard(op, [base_loc, ofs_loc, value_loc])]) - consider_setfield_gc_ptr = consider_setfield_gc__4 + # XXX location is a bit smaller, but we don't care too much + consider_strsetitem = consider_setfield_gc - def consider_getfield_gc__4(self, op): + def consider_getfield_gc(self, op): base_loc, ops0 = self.make_sure_var_in_reg(op.args[0], op.args) ofs_loc, ops1 = self.make_sure_var_in_reg(op.args[1], op.args) self.eventually_free_vars([op.args[0], op.args[1]]) @@ -624,9 +653,11 @@ return (ops0 + ops1 + more_ops + [Perform(op, [base_loc, ofs_loc], result_loc)]) - consider_getfield_gc_ptr = consider_getfield_gc__4 - consider_getfield_raw__4 = consider_getfield_gc__4 - consider_getfield_raw_ptr = consider_getfield_gc__4 + consider_getfield_raw = consider_getfield_gc + consider_getfield_raw = consider_getfield_gc + + def consider_getitem(self, op): + return self._call(op, [self.loc(arg) for arg in op.args]) def consider_zero_gc_pointers_inside(self, op): self.eventually_free_var(op.args[0]) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Sat Feb 21 09:32:18 2009 @@ -9,11 +9,11 @@ from pypy.rlib.objectmodel import we_are_translated, keepalive_until_here from pypy.annotation import model as annmodel -import history -from history import MergePoint, ResOperation, Box, Const, ConstInt, ConstPtr,\ - BoxInt, BoxPtr, ConstAddr -from codegen386.assembler import Assembler386 -from codegen386 import symbolic +from pypy.jit.metainterp import history +from pypy.jit.metainterp.history import (MergePoint, ResOperation, Box, Const, + ConstInt, ConstPtr, BoxInt, BoxPtr, ConstAddr) +from pypy.jit.backend.x86.assembler import Assembler386 +from pypy.jit.backend.x86 import symbolic class CPU386(object): debug = True @@ -143,6 +143,8 @@ operations = [mp, ResOperation(opname, livevarlist, results), ResOperation('return', results, [])] + if opname.startswith('guard_'): + operations[1].liveboxes = [] self.compile_operations(operations, verbose=False) self._compiled_ops[real_key] = mp return mp @@ -269,10 +271,12 @@ else: raise ValueError(valuebox.type) - def getvaluebox(self, frameadr, mp, argindex): + def getvaluebox(self, frameadr, guard_op, argindex): + # XXX that's plain stupid, do we care about the return value??? + box = [b for b in guard_op.liveboxes if isinstance(b, Box)][argindex] frame = getframe(frameadr) - intvalue = frame[mp.stacklocs[argindex]] - box = mp.args[argindex] + pos = guard_op.stacklocs[argindex] + intvalue = frame[pos] if isinstance(box, history.BoxInt): return history.BoxInt(intvalue) elif isinstance(box, history.BoxPtr): @@ -308,6 +312,16 @@ return res @staticmethod + def fielddescrof(S, fieldname): + ofs, size = symbolic.get_field_token(S, fieldname) + assert size == 4 + return ofs + + @staticmethod + def typefor(fielddesc): + return "int" + + @staticmethod def cast_int_to_adr(x): return llmemory.cast_ptr_to_adr(rffi.cast(llmemory.GCREF, x)) @@ -334,7 +348,6 @@ self.cpu = cpu self.frame = frame self.guard_op = guard_op - self.merge_point = guard_op.most_recent_mp def make_ready_for_return(self, return_value_box): self.cpu.assembler.make_sure_mc_exists() @@ -346,7 +359,6 @@ def make_ready_for_continuing_at(self, merge_point): # we need to make sure here that return_addr points to a code # that is ready to grab coorect values - self.merge_point = merge_point self.return_addr = merge_point.comeback_bootstrap_addr def getframe(frameadr): Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/support.py Sat Feb 21 09:32:18 2009 @@ -0,0 +1,29 @@ + +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rlib.objectmodel import we_are_translated +import ctypes + +GC_MALLOC = lltype.Ptr(lltype.FuncType([lltype.Signed], llmemory.Address)) + +def gc_malloc(size): + return llop.call_boehm_gc_alloc(llmemory.Address, size) + +def gc_malloc_fnaddr(): + """Returns the address of the Boehm 'malloc' function.""" + if we_are_translated(): + gc_malloc_ptr = llhelper(GC_MALLOC, gc_malloc) + return lltype.cast_ptr_to_int(gc_malloc_ptr) + else: + try: + from ctypes import cast, c_void_p, util + path = util.find_library('gc') + if path is None: + raise ImportError("Boehm (libgc) not found") + boehmlib = ctypes.cdll.LoadLibrary(path) + except ImportError, e: + import py + py.test.skip(str(e)) + else: + GC_malloc = boehmlib.GC_malloc + return cast(GC_malloc, c_void_p).value Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py Sat Feb 21 09:32:18 2009 @@ -1,29 +1,28 @@ import py -from codegen386.runner import CPU386 -from pyjitpl import ll_meta_interp -from test import test_basic -from pypy.jit.hintannotator.policy import StopAtXPolicy +from pypy.jit.backend.x86.runner import CPU386 +from pypy.jit.metainterp.warmspot import ll_meta_interp +from pypy.jit.metainterp.test import test_basic +from pypy.jit.metainterp.policy import StopAtXPolicy +from pypy.rlib.jit import JitDriver - -class Jit386Mixin(test_basic.JitMixin): +class Jit386Mixin(test_basic.LLJitMixin): type_system = 'lltype' + CPUClass = CPU386 def check_jumps(self, maxcount): pass - @staticmethod - def meta_interp(fn, args, **kwds): - return ll_meta_interp(fn, args, CPUClass=CPU386, **kwds) - - class TestBasic(Jit386Mixin, test_basic.BasicTests): # for the individual tests see # ====> ../../test/test_basic.py def test_bug(self): + jitdriver = JitDriver(greens = [], reds = ['n']) class X(object): pass def f(n): while n > -100: + jitdriver.can_enter_jit(n=n) + jitdriver.jit_merge_point(n=n) x = X() x.arg = 5 if n <= 0: break Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_loop_spec.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_loop_spec.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_loop_spec.py Sat Feb 21 09:32:18 2009 @@ -1,14 +1,8 @@ import py -from codegen386.runner import CPU386 -from pyjitpl import ll_meta_interp -from test import test_loop_spec +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin +from pypy.jit.metainterp.test import test_loop_spec -class TestLoopSpec(test_loop_spec.TestLoopSpec): +class TestLoopSpec(Jit386Mixin, test_loop_spec.TestLoopSpec): # for the individual tests see - # ====> ../../test/test_loop.py - - def meta_interp(self, f, args, requires_oo=False): - ###py.test.skip("in-progress") - if requires_oo: - py.test.skip("oo only") - return ll_meta_interp(f, args, CPUClass=CPU386) + # ====> ../../../metainterp/test/test_loop.py + pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_runner.py Sat Feb 21 09:32:18 2009 @@ -1,8 +1,9 @@ import py from pypy.rpython.lltypesystem import lltype, llmemory, rffi -from history import ResOperation, MergePoint, Jump -from history import BoxInt, BoxPtr, ConstInt, ConstPtr -from codegen386.runner import CPU, GuardFailed +from pypy.jit.metainterp.history import ResOperation, MergePoint, Jump +from pypy.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt, ConstPtr, + GuardOp) +from pypy.jit.backend.x86.runner import CPU, GuardFailed class FakeStats(object): pass @@ -10,11 +11,10 @@ class FakeMetaInterp(object): def handle_guard_failure(self, gf): assert isinstance(gf, GuardFailed) - assert gf.merge_point.opname == 'merge_point' self.gf = gf self.recordedvalues = [ - gf.cpu.getvaluebox(gf.frame, gf.merge_point, i).value - for i in range(len(gf.merge_point.args))] + gf.cpu.getvaluebox(gf.frame, gf.guard_op, i).value + for i in range(len(gf.guard_op.liveboxes))] gf.make_ready_for_return(BoxInt(42)) MY_VTABLE = lltype.Struct('my_vtable') # for tests only @@ -72,12 +72,12 @@ cpu = self.cpu u = lltype.malloc(U) u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u)) - ofs_box = ConstInt(cpu.offsetof(S, 'value')) - assert cpu.execute_operation('setfield_gc__4', [u_box, ofs_box, BoxInt(3)], + ofs_box = ConstInt(cpu.fielddescrof(S, 'value')) + assert cpu.execute_operation('setfield_gc', [u_box, ofs_box, BoxInt(3)], 'void') == None assert u.parent.parent.value == 3 u.parent.parent.value += 100 - assert (cpu.execute_operation('getfield_gc__4', [u_box, ofs_box], 'int') + assert (cpu.execute_operation('getfield_gc', [u_box, ofs_box], 'int') .value == 103) def test_execute_operations_in_env(self): @@ -93,20 +93,18 @@ ResOperation('int_add', [x, y], [z]), ResOperation('int_sub', [y, ConstInt(1)], [t]), ResOperation('int_eq', [t, ConstInt(0)], [u]), - MergePoint('merge_point', [t, u, z], []), - ResOperation('guard_false', [u], []), + GuardOp('guard_false', [u], []), Jump('jump', [z, t], []), ] startmp = operations[0] - othermp = operations[-3] operations[-1].jump_target = startmp + operations[-2].liveboxes = [t, u, z] cpu.compile_operations(operations) res = cpu.execute_operations_in_new_frame('foo', startmp, [BoxInt(0), BoxInt(10)], 'int') assert res.value == 42 gf = cpu.metainterp.gf - assert gf.merge_point is othermp assert cpu.metainterp.recordedvalues == [0, True, 55] assert gf.guard_op is operations[-2] @@ -114,18 +112,16 @@ vtable_for_T = lltype.malloc(MY_VTABLE, immortal=True) cpu = self.cpu cpu._cache_gcstruct2vtable = {T: vtable_for_T} - assert cpu.execute_operation('guard_true', [BoxInt(1)], 'void') == None - assert cpu.execute_operation('guard_false', [BoxInt(0)], 'void') == None - assert cpu.execute_operation('guard_value', [BoxInt(42), BoxInt(42)], - 'void') == None + for (opname, args) in [('guard_true', [BoxInt(1)]), + ('guard_false', [BoxInt(0)]), + ('guard_value', [BoxInt(42), BoxInt(42)])]: + assert cpu.execute_operation(opname, args, 'void') == None t = lltype.malloc(T) t.parent.typeptr = vtable_for_T t_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, t)) T_box = ConstInt(rffi.cast(lltype.Signed, vtable_for_T)) null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T))) assert cpu.execute_operation('guard_class', [t_box, T_box], 'void') == None - assert cpu.execute_operation('guard_nonnull', [t_box], 'void') == None - assert cpu.execute_operation('guard_isnull', [null_box], 'void') == None def test_failing_guards(self): vtable_for_T = lltype.malloc(MY_VTABLE, immortal=True) @@ -147,10 +143,6 @@ ('guard_value', [BoxInt(42), BoxInt(41)]), ('guard_class', [t_box, U_box]), ('guard_class', [u_box, T_box]), - ('guard_lt', [BoxInt(42), BoxInt(41)]), - ('guard_ge', [BoxInt(42), BoxInt(43)]), - ('guard_isnull', [u_box]), - ('guard_nonnull', [null_box]), ]: cpu.metainterp.gf = None assert cpu.execute_operation(opname, args, 'void') == None Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_send.py Sat Feb 21 09:32:18 2009 @@ -1,20 +1,19 @@ import py -from codegen386.runner import CPU386 -from pyjitpl import ll_meta_interp -from test.test_send import SendTests -from codegen386.test.test_basic import Jit386Mixin -from pypy.jit.hintannotator.policy import StopAtXPolicy +from pypy.jit.metainterp.test.test_send import SendTests +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin +from pypy.jit.metainterp.policy import StopAtXPolicy class TestSend(Jit386Mixin, SendTests): # for the individual tests see - # ====> ../../test/test_send.py + # ====> ../../../metainterp/test/test_send.py def test_call_with_additional_args(self): def externfn(a, b, c, d): return a + b*10 + c*100 + d*1000 def f(a, b, c, d): return externfn(a, b, c, d) - res = self.meta_interp(f, [1, 2, 3, 4], policy=StopAtXPolicy(externfn)) + res = self.interp_operations(f, [1, 2, 3, 4], + policy=StopAtXPolicy(externfn)) assert res == 4321 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Sat Feb 21 09:32:18 2009 @@ -784,7 +784,7 @@ def jump_after_guard_failure(self, guard_failure, loop, residual_args): guard_failure.make_ready_for_continuing_at(loop.operations[0]) for i in range(len(residual_args)): - self.cpu.setvaluebox(guard_failure.frame, guard_failure.guard_op, + self.cpu.setvaluebox(guard_failure.frame, loop.operations[0], i, residual_args[i]) def compile(self, original_boxes, live_arg_boxes): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Sat Feb 21 09:32:18 2009 @@ -34,7 +34,10 @@ class LLJitMixin(JitMixin): type_system = 'lltype' CPUClass = runner.CPU - meta_interp = staticmethod(ll_meta_interp) + + def meta_interp(self, *args, **kwds): + kwds['CPUClass'] = self.CPUClass + return ll_meta_interp(*args, **kwds) def interp_operations(self, f, args, policy=None): class DoneWithThisFrame(Exception): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Sat Feb 21 09:32:18 2009 @@ -51,21 +51,30 @@ self.check_loops(getfield_gc = 0, setfield_gc = 1) def test_loop_with_two_paths(self): + from pypy.rpython.lltypesystem import lltype + from pypy.rpython.lltypesystem.lloperation import llop myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res']) - def g(y, x): + + def l(y, x, t): + llop.debug_print(lltype.Void, y, x, t) + + def g(y, x, r): if y <= 12: - return x - 2 + res = x - 2 else: - return x + res = x + l(y, x, r) + return res + def f(x, y): res = 0 while y > 0: myjitdriver.can_enter_jit(x=x, y=y, res=res) myjitdriver.jit_merge_point(x=x, y=y, res=res) - res += g(y, x) + res += g(y, x, res) y -= 1 return res * 2 - res = self.meta_interp(f, [6, 33]) + res = self.meta_interp(f, [6, 33], policy=StopAtXPolicy(l)) assert res == f(6, 33) self.check_loop_count(2) @@ -305,7 +314,6 @@ assert loops[0].operations[0].opname == 'merge_point' assert loops[1].operations[0].opname == 'catch' - def test_example(self): myjitdriver = JitDriver(greens = ['i'], reds = ['res', 'a']) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py Sat Feb 21 09:32:18 2009 @@ -1,5 +1,4 @@ import py -py.test.skip("XXX WiP") from pypy.jit.metainterp.warmspot import rpython_ll_meta_interp, ll_meta_interp from pypy.jit.metainterp.test import test_basic from pypy.rlib.jit import JitDriver Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Sat Feb 21 09:32:18 2009 @@ -262,6 +262,10 @@ args = [] for i, arg in enumerate(e.args): v = arg.value + # HACK for x86 backend always returning int + if (isinstance(PORTALFUNC.ARGS[i], lltype.Ptr) and + isinstance(v, int)): + v = self.metainterp.cpu.cast_int_to_gcref(v) if lltype.typeOf(v) == llmemory.GCREF: v = lltype.cast_opaque_ptr(PORTALFUNC.ARGS[i], v) @@ -467,7 +471,8 @@ cpu = warmrunnerdesc.metainterp.cpu mp = loop.operations[0] box = cpu.execute_operations_in_new_frame('run_this_loop', - mp, boxes) + mp, boxes, + "int") raise warmrunnerdesc.DoneWithThisFrame(box) def must_compile_from_failure(self, guard_failure): From pedronis at codespeak.net Sat Feb 21 18:36:07 2009 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 21 Feb 2009 18:36:07 +0100 (CET) Subject: [pypy-svn] r62080 - pypy/build/bot2/pypybuildbot Message-ID: <20090221173607.D975B1684AA@codespeak.net> Author: pedronis Date: Sat Feb 21 18:36:07 2009 New Revision: 62080 Modified: pypy/build/bot2/pypybuildbot/master.py Log: schedule the app-level stackless tests too Modified: pypy/build/bot2/pypybuildbot/master.py ============================================================================== --- pypy/build/bot2/pypybuildbot/master.py (original) +++ pypy/build/bot2/pypybuildbot/master.py Sat Feb 21 18:36:07 2009 @@ -49,7 +49,8 @@ 'change_source': [], 'schedulers': [ - Nightly("nightly", [LINUX32, CPYLINUX32, APPLVLLINUX32, CPYWIN32], + Nightly("nightly", [LINUX32, CPYLINUX32, APPLVLLINUX32, CPYWIN32, + STACKLESSAPPLVLLINUX32], hour=4, minute=45), ], 'status': [status], From nshepperd at codespeak.net Sat Feb 21 23:37:22 2009 From: nshepperd at codespeak.net (nshepperd at codespeak.net) Date: Sat, 21 Feb 2009 23:37:22 +0100 (CET) Subject: [pypy-svn] r62086 - pypy/branch/new-platformcheck Message-ID: <20090221223722.A7FFE168489@codespeak.net> Author: nshepperd Date: Sat Feb 21 23:37:20 2009 New Revision: 62086 Removed: pypy/branch/new-platformcheck/ Log: Broken branch can't be synchronised with trunk cleanly. From fijal at codespeak.net Mon Feb 23 15:33:23 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 23 Feb 2009 15:33:23 +0100 (CET) Subject: [pypy-svn] r62096 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090223143323.02662168445@codespeak.net> Author: fijal Date: Mon Feb 23 15:33:23 2009 New Revision: 62096 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Log: kill the XXX don't cache and cache. Needed for jit Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll2ctypes.py Mon Feb 23 15:33:23 2009 @@ -212,40 +212,6 @@ while delayed_builders: delayed_builders.pop()() -def remove_regular_struct_content(container): - STRUCT = container._TYPE - for field_name in STRUCT._names: - FIELDTYPE = getattr(STRUCT, field_name) - if not isinstance(FIELDTYPE, lltype.ContainerType): - delattr(container, field_name) - -def convert_array(container, carray=None): - ARRAY = container._TYPE - if carray is None: - # if 'container' is an inlined substructure, convert the whole - # bigger structure at once - parent, parentindex = lltype.parentlink(container) - if parent is not None: - convert_struct(parent) - return - # regular case: allocate a new ctypes array of the proper type - cls = get_ctypes_type(ARRAY) - carray = cls._malloc(container.getlength()) - add_storage(container, _array_mixin, carray) - if not isinstance(ARRAY.OF, lltype.ContainerType): - # fish that we have enough space - ctypes_array = ctypes.cast(carray.items, - ctypes.POINTER(carray.items._type_)) - for i in range(container.getlength()): - item_value = container.items[i] # fish fish - ctypes_array[i] = lltype2ctypes(item_value) - remove_regular_array_content(container) - else: - assert isinstance(ARRAY.OF, lltype.Struct) - for i in range(container.getlength()): - item_ptr = container.items[i] # fish fish - convert_struct(item_ptr, carray.items[i]) - def convert_struct(container, cstruct=None): STRUCT = container._TYPE if cstruct is None: @@ -282,6 +248,40 @@ raise NotImplementedError('inlined field', FIELDTYPE) remove_regular_struct_content(container) +def remove_regular_struct_content(container): + STRUCT = container._TYPE + for field_name in STRUCT._names: + FIELDTYPE = getattr(STRUCT, field_name) + if not isinstance(FIELDTYPE, lltype.ContainerType): + delattr(container, field_name) + +def convert_array(container, carray=None): + ARRAY = container._TYPE + if carray is None: + # if 'container' is an inlined substructure, convert the whole + # bigger structure at once + parent, parentindex = lltype.parentlink(container) + if parent is not None: + convert_struct(parent) + return + # regular case: allocate a new ctypes array of the proper type + cls = get_ctypes_type(ARRAY) + carray = cls._malloc(container.getlength()) + add_storage(container, _array_mixin, carray) + if not isinstance(ARRAY.OF, lltype.ContainerType): + # fish that we have enough space + ctypes_array = ctypes.cast(carray.items, + ctypes.POINTER(carray.items._type_)) + for i in range(container.getlength()): + item_value = container.items[i] # fish fish + ctypes_array[i] = lltype2ctypes(item_value) + remove_regular_array_content(container) + else: + assert isinstance(ARRAY.OF, lltype.Struct) + for i in range(container.getlength()): + item_ptr = container.items[i] # fish fish + convert_struct(item_ptr, carray.items[i]) + def remove_regular_array_content(container): for i in range(container.getlength()): container.items[i] = None @@ -620,9 +620,12 @@ c_tp = get_ctypes_type(T.TO) storage._normalized_ctype = c_tp if normalize and getattr(T.TO, '_arrayfld', None): - # XXX doesn't cache - c_tp = build_ctypes_struct(T.TO, [], - len(getattr(storage, T.TO._arrayfld).items)) + try: + c_tp = _ctypes_cache[T.TO] + except KeyError: + c_tp = build_ctypes_struct(T.TO, [], + len(getattr(storage, T.TO._arrayfld).items)) + _ctypes_cache[T.TO] = c_tp p = ctypes.cast(p, ctypes.POINTER(c_tp)) elif normalize and hasattr(storage, '_normalized_ctype'): p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype)) From fijal at codespeak.net Mon Feb 23 15:34:46 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 23 Feb 2009 15:34:46 +0100 (CET) Subject: [pypy-svn] r62097 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090223143446.87BB5168445@codespeak.net> Author: fijal Date: Mon Feb 23 15:34:45 2009 New Revision: 62097 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_exception.py (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Log: A bit of progress with x86 backend, fix two bugs Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Mon Feb 23 15:34:45 2009 @@ -267,6 +267,8 @@ ops = [Store(v_to_spill, selected_reg, newloc)] else: ops = [] + del self.reg_bindings[v_to_spill] + self.free_regs.append(selected_reg) return selected_reg, ops+[Load(v, convert_to_imm(v), selected_reg)] return convert_to_imm(v), [] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/runner.py Mon Feb 23 15:34:45 2009 @@ -206,6 +206,7 @@ range(len(valueboxes))]) if self.debug: llop.debug_print(lltype.Void, 'exec:', name, values_repr) + self.keepalives_index = len(self.keepalives) res = self.execute_call(startmp, func, values_as_int) if result_type == 'void': Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_exception.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_exception.py Mon Feb 23 15:34:45 2009 @@ -0,0 +1,12 @@ + +import py +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin +from pypy.jit.metainterp.test.test_exception import ExceptionTests + +py.test.skip("exceptions are broken") + +class TestExceptions(Jit386Mixin, ExceptionTests): + # for the individual tests see + # ====> ../../../metainterp/test/test_exception.py + pass + Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Mon Feb 23 15:34:45 2009 @@ -3,10 +3,11 @@ """ import py -from history import ResOperation, MergePoint, Jump, BoxInt, ConstInt -from codegen386.runner import CPU, GuardFailed +from pypy.jit.metainterp.history import (ResOperation, MergePoint, Jump, + BoxInt, ConstInt, GuardOp) +from pypy.jit.backend.x86.runner import CPU, GuardFailed from pypy.rpython.lltypesystem import lltype -from codegen386.test.test_runner import FakeMetaInterp, FakeStats +from pypy.jit.backend.x86.test.test_runner import FakeMetaInterp, FakeStats def test_simple_loop(): meta_interp = FakeMetaInterp() @@ -22,13 +23,14 @@ # i += 1 operations = [ MergePoint('merge_point', [i, flag], []), - ResOperation('guard_true', [flag], []), + GuardOp('guard_true', [flag], []), ResOperation('int_add', [i, ConstInt(1)], [i_0]), ResOperation('int_lt', [i_0, ConstInt(5)], [flag_0]), Jump('jump', [i_0, flag_0], []), ] startmp = operations[0] operations[-1].jump_target = startmp + operations[1].liveboxes = [i, flag] cpu.compile_operations(operations) res = cpu.execute_operations_in_new_frame('foo', startmp, @@ -42,36 +44,6 @@ longevity = regalloc.longevity assert longevity == {i: (0, 2), flag: (0, 1), i_0: (2, 4), flag_0: (3, 4)} -def test_longevity_after_merge_point(): - cpu = CPU(rtyper=None, stats=FakeStats()) - meta_interp = FakeMetaInterp() - cpu.set_meta_interp(meta_interp) - i = BoxInt(0) # a loop variable - j = BoxInt(0) - flag = BoxInt(1) # True - flag_0 = BoxInt(1) # True - operations = [ - MergePoint('merge_point', [i, flag, j], []), - ResOperation('guard_false', [flag], []), - ResOperation('int_lt', [i, ConstInt(5)], [flag_0]), - Jump('jump', [ConstInt(3), flag_0, ConstInt(1)], []), - ] - startmp = operations[0] - operations[-1].jump_target = startmp - - cpu.compile_operations(operations) - res = cpu.execute_operations_in_new_frame('foo', startmp, - [BoxInt(0), BoxInt(1), BoxInt(3)], - 'int') - assert res.value == 42 - # assert stuff - regalloc = cpu.assembler._regalloc - # no leakage, args to merge_point - assert regalloc.current_stack_depth == 3 - longevity = regalloc.longevity - assert longevity[j] == (0, 1) - assert meta_interp.recordedvalues == [0, True, 3] - def test_longer_loop(): """ This test checks whether register allocation can reclaim back unused registers @@ -103,7 +75,7 @@ return [x, y, i, i < 5] operations = [ MergePoint('merge_point', [x, y, i, flag], []), - ResOperation('guard_true', [flag], []), + GuardOp('guard_true', [flag], []), ResOperation('int_add', [y, x], [v0]), ResOperation('int_mul', [v0, i], [v1]), ResOperation('int_sub', [v1, x], [x0]), @@ -116,6 +88,7 @@ ] startmp = operations[0] operations[-1].jump_target = startmp + operations[1].liveboxes = [x, y, i, flag] cpu.compile_operations(operations) From arigo at codespeak.net Tue Feb 24 12:04:51 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Feb 2009 12:04:51 +0100 (CET) Subject: [pypy-svn] r62106 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090224110451.C5352168493@codespeak.net> Author: arigo Date: Tue Feb 24 12:04:49 2009 New Revision: 62106 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Add a class Options collecting the testing options that we can enable or disable. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Tue Feb 24 12:04:49 2009 @@ -117,7 +117,7 @@ history = metainterp.history loop.operations = history.operations close_loop(loop, loop.operations[0], endliveboxes) - old_loop = optimize.optimize_loop(metainterp, old_loops, loop) + old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop) if old_loop is not None: return old_loop finish_loop_or_bridge(metainterp, loop, loop.operations[0]) @@ -153,7 +153,7 @@ op = Jump('jump', endliveboxes, []) operations.append(op) # - old_loop = optimize.optimize_bridge(metainterp, old_loops, bridge) + old_loop = optimize.optimize_bridge(metainterp.options, old_loops, bridge) if old_loop is None: return None bridge.jump_to = old_loop Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Feb 24 12:04:49 2009 @@ -206,15 +206,15 @@ return "" % (self.source, flags) -def optimize_loop(metainterp, old_loops, loop): - if not metainterp._specialize: # for tests only +def optimize_loop(options, old_loops, loop): + if not options.specialize: # for tests only if old_loops: return old_loops[0] else: return None # This does "Perfect specialization" as per doc/jitpl5.txt. - perfect_specializer = PerfectSpecializer(loop) + perfect_specializer = PerfectSpecializer(loop, options) perfect_specializer.find_nodes() perfect_specializer.intersect_input_and_output() for old_loop in old_loops: @@ -223,11 +223,11 @@ perfect_specializer.optimize_loop() return None -def optimize_bridge(metainterp, old_loops, operations): - if not metainterp._specialize: # for tests only +def optimize_bridge(options, old_loops, bridge): + if not options.specialize: # for tests only return old_loops[0] - perfect_specializer = PerfectSpecializer(operations) + perfect_specializer = PerfectSpecializer(bridge, options) perfect_specializer.find_nodes() for old_loop in old_loops: if perfect_specializer.match(old_loop.operations): @@ -238,8 +238,9 @@ class PerfectSpecializer(object): - def __init__(self, loop): + def __init__(self, loop, options): self.loop = loop + self.options = options self.nodes = {} self.dependency_graph = [] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Feb 24 12:04:49 2009 @@ -405,32 +405,32 @@ args.append(ConstInt(0)) else: args.append(ConstPtr(lltype.nullptr(llmemory.GCREF.TO))) - self.execute_with_exc('newlist', args, 'ptr') + return self.execute_with_exc('newlist', args, 'ptr') @arguments("builtin", "varargs") def opimpl_append(self, descr, varargs): args = [descr.append_func] + varargs - self.execute_with_exc('append', args, 'void') + return self.execute_with_exc('append', args, 'void') @arguments("builtin", "varargs") def opimpl_insert(self, descr, varargs): args = [descr.insert_func] + varargs - self.execute_with_exc('insert', args, 'void') + return self.execute_with_exc('insert', args, 'void') @arguments("builtin", "varargs") def opimpl_pop(self, descr, varargs): args = [descr.pop_func] + varargs - self.execute_with_exc('pop', args, descr.tp) + return self.execute_with_exc('pop', args, descr.tp) @arguments("builtin", "varargs") def opimpl_len(self, descr, varargs): args = [descr.len_func] + varargs - self.execute_with_exc('len', args, 'int') + return self.execute_with_exc('len', args, 'int') @arguments("builtin", "varargs") def opimpl_listnonzero(self, descr, varargs): args = [descr.nonzero_func] + varargs - self.execute_with_exc('listnonzero', args, 'int') + return self.execute_with_exc('listnonzero', args, 'int') @arguments("indirectcallset", "box", "varargs") def opimpl_indirect_call(self, indirectcallset, box, varargs): @@ -662,11 +662,11 @@ class OOMetaInterp(object): num_green_args = 0 - def __init__(self, portal_graph, graphs, cpu, stats, specialize): + def __init__(self, portal_graph, graphs, cpu, stats, options): self.portal_graph = portal_graph self.cpu = cpu self.stats = stats - self._specialize = specialize + self.options = options self.compiled_merge_points = r_dict(history.mp_eq, history.mp_hash) # { greenkey: list-of-MergePoints } @@ -1006,3 +1006,10 @@ class GenerateMergePoint(Exception): def __init__(self, args): self.argboxes = args + + +class Options: + def __init__(self, specialize=True): + self.specialize = specialize + def _freeze_(self): + return True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Tue Feb 24 12:04:49 2009 @@ -12,7 +12,7 @@ from pypy.rlib.rarithmetic import r_uint from pypy.jit.metainterp import support, history, pyjitpl -from pypy.jit.metainterp.pyjitpl import OOMetaInterp +from pypy.jit.metainterp.pyjitpl import OOMetaInterp, Options from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp.policy import JitPolicy @@ -97,9 +97,9 @@ def _freeze_(self): return True - def build_meta_interp(self, specialize=True, - CPUClass=runner.CPU, view="auto", - translate_support_code=False): + def build_meta_interp(self, CPUClass=runner.CPU, view="auto", + translate_support_code=False, **kwds): + opt = Options(**kwds) self.stats = history.Stats() cpu = CPUClass(self.translator.rtyper, self.stats, translate_support_code) @@ -118,8 +118,7 @@ self.translator.graphs.append(graph) self.portal_graph = graph self.jitdriver = block.operations[pos].args[1].value - self.metainterp = OOMetaInterp(graph, graphs, cpu, self.stats, - specialize) + self.metainterp = OOMetaInterp(graph, graphs, cpu, self.stats, opt) def make_enter_function(self): WarmEnterState = make_state_class(self) From arigo at codespeak.net Tue Feb 24 14:29:33 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Feb 2009 14:29:33 +0100 (CET) Subject: [pypy-svn] r62107 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp-bak metainterp/test Message-ID: <20090224132933.F35B8168490@codespeak.net> Author: arigo Date: Tue Feb 24 14:29:31 2009 New Revision: 62107 Added: pypy/branch/pyjitpl5/pypy/jit/metainterp-bak/ - copied from r62106, pypy/branch/pyjitpl5/pypy/jit/metainterp/ Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Make a backup of metainterp in metainterp-bak, and comment out temporarily the list spec node from metainterp. This is mostly an effort of trying to understand what is going on :-) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Tue Feb 24 14:29:31 2009 @@ -77,9 +77,9 @@ 'guard_false' : (('bool',), None), 'guard_value' : (('int', 'int'), None), 'guard_class' : (('ptr', 'ptr'), None), - 'guard_no_exception' : ((), None), - 'guard_exception' : (('ptr',), 'ptr'), - 'guard_nonvirtualized__4' : (('ptr', 'int'), None), + 'guard_no_exception' : ((), None), + 'guard_exception' : (('ptr',), 'ptr'), + 'guard_nonvirtualized' : (('ptr', 'ptr', 'int'), None), 'guard_builtin' : (('ptr',), None), 'newstr' : (('int',), 'ptr'), 'strlen' : (('ptr',), 'int'), @@ -568,11 +568,11 @@ def op_guard_builtin(self, b): pass - def op_guard_true(self, value, *livevars): + def op_guard_true(self, value): if not value: raise GuardFailed - def op_guard_false(self, value, *livevars): + def op_guard_false(self, value): if value: raise GuardFailed @@ -618,7 +618,7 @@ op_guard_is = op_guard_eq op_guard_isnot = op_guard_ne - def op_guard_class(self, value, expected_class, *livevars): + def op_guard_class(self, value, expected_class): value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) expected_class = llmemory.cast_adr_to_ptr( self.cpu.cast_int_to_adr(expected_class), @@ -630,12 +630,12 @@ if value != expected_value: raise GuardFailed - def op_guard_nonvirtualized__4(self, value, for_accessing_field): + def op_guard_nonvirtualized(self, value, expected_class, + for_accessing_field): + self.op_guard_class(value, expected_class) if heaptracker.cast_vable(value).vable_rti: raise GuardFailed # some other code is already in control - op_guard_nonvirtualized_ptr = op_guard_nonvirtualized__4 - def op_guard_no_exception(self): if self.last_exception: self.last_exception_handled = True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Tue Feb 24 14:29:31 2009 @@ -14,26 +14,26 @@ MAX_MAKE_NEW_VARS = 16 -class BuiltinDescr(history.AbstractValue): - pass +##class BuiltinDescr(history.AbstractValue): +## pass -class ListDescr(BuiltinDescr): - def __init__(self, getfunc, setfunc, malloc_func, append_func, - pop_func, insert_func, len_func, nonzero_func, tp): - self.setfunc = setfunc - self.getfunc = getfunc - self.malloc_func = malloc_func - self.append_func = append_func - self.insert_func = insert_func - self.pop_func = pop_func - self.len_func = len_func - self.nonzero_func = nonzero_func - self.tp = tp +##class ListDescr(BuiltinDescr): +## def __init__(self, getfunc, setfunc, malloc_func, append_func, +## pop_func, insert_func, len_func, nonzero_func, tp): +## self.setfunc = setfunc +## self.getfunc = getfunc +## self.malloc_func = malloc_func +## self.append_func = append_func +## self.insert_func = insert_func +## self.pop_func = pop_func +## self.len_func = len_func +## self.nonzero_func = nonzero_func +## self.tp = tp - def equals(self, other): - if isinstance(other, ListDescr): - return True - return False +## def equals(self, other): +## if isinstance(other, ListDescr): +## return True +## return False class JitCode(history.AbstractValue): def __init__(self, name): @@ -529,7 +529,7 @@ c_fieldname.value) self.emit(offset) self.register_var(op.result) - self._eventualy_builtin(op.result) + #self._eventualy_builtin(op.result) def serialize_op_setfield(self, op): if self.is_typeptr_getset(op): @@ -590,31 +590,30 @@ self.emit('jit_merge_point') assert ([self.var_position(i) for i in op.args[2:]] == range(0, 2*(len(op.args) - 2), 2)) - for i in range(2, len(op.args)): - arg = op.args[i] - self._eventualy_builtin(arg) - +## for i in range(2, len(op.args)): +## arg = op.args[i] +## self._eventualy_builtin(arg) elif op.args[0].value == 'can_enter_jit': self.emit('can_enter_jit') self.emit_varargs(op.args[2:]) - def _eventualy_builtin(self, arg, need_length=True): - if isinstance(arg.concretetype, lltype.Ptr): - # XXX very complex logic for getting all things - # that are pointers, but not objects - is_list = False - if isinstance(arg.concretetype.TO, lltype.GcArray): - is_list = True - if isinstance(arg.concretetype.TO, lltype.GcStruct): - if arg.concretetype.TO._hints.get('list'): - is_list = True - if is_list: - descr = self.codewriter.list_descr_for_tp(arg.concretetype) - self.emit('guard_builtin', self.var_position(arg), - self.get_position(descr)) - if need_length: - self.emit('guard_len', self.var_position(arg), - self.get_position(descr)) +## def _eventualy_builtin(self, arg, need_length=True): +## if isinstance(arg.concretetype, lltype.Ptr): +## # XXX very complex logic for getting all things +## # that are pointers, but not objects +## is_list = False +## if isinstance(arg.concretetype.TO, lltype.GcArray): +## is_list = True +## if isinstance(arg.concretetype.TO, lltype.GcStruct): +## if arg.concretetype.TO._hints.get('list'): +## is_list = True +## if is_list: +## descr = self.codewriter.list_descr_for_tp(arg.concretetype) +## self.emit('guard_builtin', self.var_position(arg), +## self.get_position(descr)) +## if need_length: +## self.emit('guard_len', self.var_position(arg), +## self.get_position(descr)) #def serialize_op_direct_call(self, op): # color = support.guess_call_kind(self.codewriter.hannotator, op) @@ -655,33 +654,33 @@ c_func, TP = support.builtin_func_for_spec(self.codewriter.rtyper, oopspec_name, ll_args, op.result.concretetype) - if oopspec_name.startswith('list') or oopspec_name == 'newlist': - if oopspec_name.startswith('list.getitem'): - opname = oopspec_name[len('list.'):] - elif oopspec_name.startswith('list.setitem'): - opname = oopspec_name[len('list.'):] - elif oopspec_name == 'newlist': - opname = 'newlist' - elif oopspec_name == 'list.append': - opname = 'append' - elif oopspec_name == 'list.pop': - opname = 'pop' - elif oopspec_name == 'list.len': - opname = 'len' - elif oopspec_name == 'list.insert': - opname = 'insert' - elif oopspec_name == 'list.nonzero': - opname = 'listnonzero' - else: - raise NotImplementedError("not supported %s" % oopspec_name) - self.emit(opname) - ld = self.codewriter.list_descr_for_tp(TP) - self.emit(self.get_position(ld)) - self.emit_varargs(args) - self.register_var(op.result) - if opname == 'newlist': - self._eventualy_builtin(op.result, False) - return +## if oopspec_name.startswith('list') or oopspec_name == 'newlist': +## if oopspec_name.startswith('list.getitem'): +## opname = oopspec_name[len('list.'):] +## elif oopspec_name.startswith('list.setitem'): +## opname = oopspec_name[len('list.'):] +## elif oopspec_name == 'newlist': +## opname = 'newlist' +## elif oopspec_name == 'list.append': +## opname = 'append' +## elif oopspec_name == 'list.pop': +## opname = 'pop' +## elif oopspec_name == 'list.len': +## opname = 'len' +## elif oopspec_name == 'list.insert': +## opname = 'insert' +## elif oopspec_name == 'list.nonzero': +## opname = 'listnonzero' +## else: +## raise NotImplementedError("not supported %s" % oopspec_name) +## self.emit(opname) +## ld = self.codewriter.list_descr_for_tp(TP) +## self.emit(self.get_position(ld)) +## self.emit_varargs(args) +## self.register_var(op.result) +## if opname == 'newlist': +## self._eventualy_builtin(op.result, False) +## return if oopspec_name.endswith('_foldable'): opname = 'green_call_%s' else: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py Tue Feb 24 14:29:31 2009 @@ -22,14 +22,14 @@ return lltype.cast_primitive(EXPECTED_TYPE, x) def cast_vable(p): - T = lltype.Ptr(lltype.typeOf(p._obj.container)) + T = lltype.Ptr(lltype.typeOf(p._obj._normalizedcontainer())) p = lltype.cast_opaque_ptr(T, p) STRUCT = cast_vable_type(T.TO) return lltype.cast_pointer(lltype.Ptr(STRUCT), p) def cast_vable_type(STRUCT): assert STRUCT._hints.get('virtualizable2'), \ - "not a virtualizable2: %r" % (p,) + "not a virtualizable2: %r" % (STRUCT,) while True: _, PARENT = STRUCT._first_struct() if PARENT is None or not PARENT._hints.get('virtualizable2'): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Tue Feb 24 14:29:31 2009 @@ -522,3 +522,9 @@ ResOpGraphPage(graphs, errmsg, highlightops).display() # ---------------------------------------------------------------- + +class Options: + def __init__(self, specialize=True): + self.specialize = specialize + def _freeze_(self): + return True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Feb 24 14:29:31 2009 @@ -1,19 +1,21 @@ from pypy.jit.metainterp.history import (Box, Const, ConstInt, BoxInt, MergePoint, ResOperation, Jump) +from pypy.jit.metainterp.history import Options from pypy.jit.metainterp.heaptracker import (always_pure_operations, operations_without_side_effects, operation_never_raises) from pypy.jit.metainterp.specnode import (FixedClassSpecNode, - FixedListSpecNode, + #FixedListSpecNode, VirtualInstanceSpecNode, VirtualizableSpecNode, NotSpecNode, DelayedSpecNode, SpecNodeWithBox, - DelayedListSpecNode, - VirtualListSpecNode) + #DelayedListSpecNode, + #VirtualListSpecNode, + ) from pypy.rlib.objectmodel import we_are_translated -from pypy.jit.metainterp.codewriter import ListDescr +#from pypy.jit.metainterp.codewriter import ListDescr class CancelInefficientLoop(Exception): pass @@ -33,8 +35,8 @@ self.allocations = [] self.setfields = [] # the same as above, but for lists and for running setitem - self.list_allocations = [] - self.setitems = [] +## self.list_allocations = [] +## self.setitems = [] def deal_with_box(self, box, nodes, liveboxes, memo, ready): if isinstance(box, Const) or box not in nodes: @@ -49,16 +51,17 @@ virtual = instnode.virtual virtualized = instnode.virtualized if virtual: - if isinstance(instnode.cls.source, ListDescr): - ld = instnode.cls.source - assert isinstance(ld, ListDescr) - alloc_offset = len(self.list_allocations) - malloc_func = ld.malloc_func - assert instnode.cursize != -1 - self.list_allocations.append((malloc_func, - instnode.cursize)) - res = (alloc_offset + 1) << 16 - else: +## if isinstance(instnode.cls.source, ListDescr): +## ld = instnode.cls.source +## assert isinstance(ld, ListDescr) +## alloc_offset = len(self.list_allocations) +## malloc_func = ld.malloc_func +## assert instnode.cursize != -1 +## self.list_allocations.append((malloc_func, +## instnode.cursize)) +## res = (alloc_offset + 1) << 16 +## else: + if 1: alloc_offset = len(self.allocations) self.allocations.append(instnode.cls.source.getint()) res = alloc_offset @@ -66,12 +69,13 @@ for ofs, node in instnode.curfields.items(): num = self.deal_with_box(node.source, nodes, liveboxes, memo, ready) - if isinstance(instnode.cls.source, ListDescr): - ld = instnode.cls.source - x = (alloc_offset + 1) << 16 - assert ofs < instnode.cursize - self.setitems.append((ld.setfunc, x, ofs, num)) - else: +## if isinstance(instnode.cls.source, ListDescr): +## ld = instnode.cls.source +## x = (alloc_offset + 1) << 16 +## assert ofs < instnode.cursize +## self.setitems.append((ld.setfunc, x, ofs, num)) +## else: + if 1: self.setfields.append((alloc_offset, ofs, num)) elif virtualized: res = ~len(liveboxes) @@ -135,16 +139,16 @@ not self.expanded_fields): if self.cls is None: return NotSpecNode() - if isinstance(known_class, ListDescr): - return FixedListSpecNode(known_class) +## if isinstance(known_class, ListDescr): +## return FixedListSpecNode(known_class) return FixedClassSpecNode(known_class) if not other.escaped: - if (isinstance(known_class, ListDescr) - and self.cursize != other.origsize): - # or DelayedListSpecNode, later on - self.escaped = True - other.escaped = True - return FixedListSpecNode(known_class) +## if (isinstance(known_class, ListDescr) +## and self.cursize != other.origsize): +## # or DelayedListSpecNode, later on +## self.escaped = True +## other.escaped = True +## return FixedListSpecNode(known_class) fields = [] if self is other: d = other.curfields.copy() @@ -160,9 +164,9 @@ self.origfields[ofs] = InstanceNode(node.source.clonebox()) specnode = NotSpecNode() fields.append((ofs, specnode)) - if isinstance(known_class, ListDescr): - return VirtualListSpecNode(known_class, fields, - other.cursize) +## if isinstance(known_class, ListDescr): +## return VirtualListSpecNode(known_class, fields, +## other.cursize) return VirtualInstanceSpecNode(known_class, fields) if not other.virtualized and self.expanded_fields: fields = [] @@ -171,8 +175,8 @@ for ofs in lst: specnode = SpecNodeWithBox(self.origfields[ofs].source) fields.append((ofs, specnode)) - if isinstance(known_class, ListDescr): - return DelayedListSpecNode(known_class, fields) +## if isinstance(known_class, ListDescr): +## return DelayedListSpecNode(known_class, fields) return DelayedSpecNode(known_class, fields) else: assert self is other @@ -238,7 +242,7 @@ class PerfectSpecializer(object): - def __init__(self, loop, options): + def __init__(self, loop, options=Options()): self.loop = loop self.options = options self.nodes = {} @@ -276,7 +280,7 @@ self.nodes[box] = fieldnode if (self.first_escaping_op and instnode.cls and - not isinstance(instnode.cls.source, ListDescr)): + 1): ##not isinstance(instnode.cls.source, ListDescr)): instnode.expanded_fields[field] = None def find_nodes_insert(self, instnode, field, fieldnode): @@ -303,32 +307,32 @@ self.nodes[box] = instnode self.first_escaping_op = False continue - elif opname == 'newlist': - box = op.results[0] - instnode = InstanceNode(box, escaped=False) - self.nodes[box] = instnode - self.first_escaping_op = False - if (isinstance(op.args[1], ConstInt) or - self.nodes[op.args[1]].const): - size = self.getsource(op.args[1]).getint() - instnode.cursize = size - instnode.origsize = size - # XXX following guard_builtin will set the - # correct class, otherwise it's a mess - continue - elif opname == 'guard_builtin': - instnode = self.nodes[op.args[0]] - # all builtins have equal classes - instnode.cls = InstanceNode(op.args[1]) - continue - elif opname == 'guard_len': - instnode = self.nodes[op.args[0]] - if instnode.cursize == -1: - instnode = self.nodes[op.args[0]] - size = op.args[1].getint() - instnode.cursize = size - instnode.origsize = size - continue +## elif opname == 'newlist': +## box = op.results[0] +## instnode = InstanceNode(box, escaped=False) +## self.nodes[box] = instnode +## self.first_escaping_op = False +## if (isinstance(op.args[1], ConstInt) or +## self.nodes[op.args[1]].const): +## size = self.getsource(op.args[1]).getint() +## instnode.cursize = size +## instnode.origsize = size +## # XXX following guard_builtin will set the +## # correct class, otherwise it's a mess +## continue +## elif opname == 'guard_builtin': +## instnode = self.nodes[op.args[0]] +## # all builtins have equal classes +## instnode.cls = InstanceNode(op.args[1]) +## continue +## elif opname == 'guard_len': +## instnode = self.nodes[op.args[0]] +## if instnode.cursize == -1: +## instnode = self.nodes[op.args[0]] +## size = op.args[1].getint() +## instnode.cursize = size +## instnode.origsize = size +## continue elif opname == 'setfield_gc': instnode = self.getnode(op.args[0]) fieldbox = op.args[1] @@ -345,81 +349,81 @@ box = op.results[0] self.find_nodes_getfield(instnode, field, box) continue - elif opname == 'getitem': - instnode = self.getnode(op.args[1]) - fieldbox = op.args[2] - if (isinstance(fieldbox, ConstInt) or - self.nodes[op.args[2]].const): - field = self.getsource(fieldbox).getint() - if field < 0: - field = instnode.cursize + field - box = op.results[0] - self.find_nodes_getfield(instnode, field, box) - continue - else: - instnode.escaped = True - self.nodes[op.results[0]] = InstanceNode(op.results[0], - escaped=True) - continue - elif opname == 'append': - instnode = self.getnode(op.args[1]) - assert isinstance(instnode.cls.source, ListDescr) - if instnode.cursize != -1: - field = instnode.cursize - instnode.cursize += 1 - self.find_nodes_setfield(instnode, field, - self.getnode(op.args[2])) - continue - elif opname == 'insert': - instnode = self.getnode(op.args[1]) - assert isinstance(instnode.cls.source, ListDescr) - if instnode.cursize != -1: - fieldbox = self.getsource(op.args[2]) - assert isinstance(fieldbox, Const) or fieldbox.const - field = fieldbox.getint() - if field < 0: - field = instnode.cursize + field - self.find_nodes_insert(instnode, field, - self.getnode(op.args[3])) - continue - elif opname == 'pop': - instnode = self.getnode(op.args[1]) - assert isinstance(instnode.cls.source, ListDescr) - if instnode.cursize != -1: - instnode.cursize -= 1 - field = instnode.cursize - self.find_nodes_getfield(instnode, field, op.results[0]) - if field in instnode.curfields: - del instnode.curfields[field] - continue - self.nodes[op.results[0]] = InstanceNode(op.results[0], - escaped=True) - self.dependency_graph.append((instnode, - self.nodes[op.results[0]])) - continue - elif opname == 'len' or opname == 'listnonzero': - instnode = self.getnode(op.args[1]) - if not instnode.escaped: - assert instnode.cursize != -1 - lgtbox = op.results[0].constbox() - self.nodes[op.results[0]] = InstanceNode(lgtbox, const=True) - continue - elif opname == 'setitem': - instnode = self.getnode(op.args[1]) - fieldbox = op.args[2] - if (isinstance(fieldbox, ConstInt) - or self.nodes[op.args[2]].const): - field = self.getsource(fieldbox).getint() - if field < 0: - field = instnode.cursize + field - assert field < instnode.cursize - self.find_nodes_setfield(instnode, field, - self.getnode(op.args[3])) - continue - else: - self.dependency_graph.append((instnode, - self.getnode(op.args[3]))) - instnode.escaped = True +## elif opname == 'getitem': +## instnode = self.getnode(op.args[1]) +## fieldbox = op.args[2] +## if (isinstance(fieldbox, ConstInt) or +## self.nodes[op.args[2]].const): +## field = self.getsource(fieldbox).getint() +## if field < 0: +## field = instnode.cursize + field +## box = op.results[0] +## self.find_nodes_getfield(instnode, field, box) +## continue +## else: +## instnode.escaped = True +## self.nodes[op.results[0]] = InstanceNode(op.results[0], +## escaped=True) +## continue +## elif opname == 'append': +## instnode = self.getnode(op.args[1]) +## assert isinstance(instnode.cls.source, ListDescr) +## if instnode.cursize != -1: +## field = instnode.cursize +## instnode.cursize += 1 +## self.find_nodes_setfield(instnode, field, +## self.getnode(op.args[2])) +## continue +## elif opname == 'insert': +## instnode = self.getnode(op.args[1]) +## assert isinstance(instnode.cls.source, ListDescr) +## if instnode.cursize != -1: +## fieldbox = self.getsource(op.args[2]) +## assert isinstance(fieldbox, Const) or fieldbox.const +## field = fieldbox.getint() +## if field < 0: +## field = instnode.cursize + field +## self.find_nodes_insert(instnode, field, +## self.getnode(op.args[3])) +## continue +## elif opname == 'pop': +## instnode = self.getnode(op.args[1]) +## assert isinstance(instnode.cls.source, ListDescr) +## if instnode.cursize != -1: +## instnode.cursize -= 1 +## field = instnode.cursize +## self.find_nodes_getfield(instnode, field, op.results[0]) +## if field in instnode.curfields: +## del instnode.curfields[field] +## continue +## self.nodes[op.results[0]] = InstanceNode(op.results[0], +## escaped=True) +## self.dependency_graph.append((instnode, +## self.nodes[op.results[0]])) +## continue +## elif opname == 'len' or opname == 'listnonzero': +## instnode = self.getnode(op.args[1]) +## if not instnode.escaped: +## assert instnode.cursize != -1 +## lgtbox = op.results[0].constbox() +## self.nodes[op.results[0]] = InstanceNode(lgtbox, const=True) +## continue +## elif opname == 'setitem': +## instnode = self.getnode(op.args[1]) +## fieldbox = op.args[2] +## if (isinstance(fieldbox, ConstInt) +## or self.nodes[op.args[2]].const): +## field = self.getsource(fieldbox).getint() +## if field < 0: +## field = instnode.cursize + field +## assert field < instnode.cursize +## self.find_nodes_setfield(instnode, field, +## self.getnode(op.args[3])) +## continue +## else: +## self.dependency_graph.append((instnode, +## self.getnode(op.args[3]))) +## instnode.escaped = True elif opname == 'guard_class': instnode = self.getnode(op.args[0]) if instnode.cls is None: @@ -529,10 +533,11 @@ rev_boxes[fieldbox] = len(liveboxes) liveboxes.append(fieldbox) fieldindex = ~rev_boxes[fieldbox] - if node.cls is not None and isinstance(node.cls.source, ListDescr): - f = node.cls.source.setfunc - storage.setitems.append((f, index, ofs, fieldindex)) - else: +## if node.cls is not None and isinstance(node.cls.source, ListDescr): +## f = node.cls.source.setfunc +## storage.setitems.append((f, index, ofs, fieldindex)) +## else: + if 1: storage.setfields.append((index, ofs, fieldindex)) if not we_are_translated(): items = [box for box in liveboxes if isinstance(box, Box)] @@ -681,13 +686,13 @@ continue # otherwise we need this getfield, but it does not # invalidate caches - elif opname == 'getitem': - instnode = self.nodes[op.args[1]] - ofsbox = self.getsource(op.args[2]) - if isinstance(ofsbox, ConstInt): - ofs = ofsbox.getint() - if self.optimize_getfield(instnode, ofs, op.results[0]): - continue +## elif opname == 'getitem': +## instnode = self.nodes[op.args[1]] +## ofsbox = self.getsource(op.args[2]) +## if isinstance(ofsbox, ConstInt): +## ofs = ofsbox.getint() +## if self.optimize_getfield(instnode, ofs, op.results[0]): +## continue elif opname == 'new_with_vtable': # self.nodes[op.results[0]] keep the value from Steps (1,2) instnode = self.nodes[op.results[0]] @@ -695,60 +700,60 @@ instnode.virtual = True assert instnode.cls is not None continue - elif opname == 'newlist': - instnode = self.nodes[op.results[0]] - assert isinstance(instnode.cls.source, ListDescr) - if not instnode.escaped: - instnode.virtual = True - valuesource = self.getsource(op.args[2]) - instnode.cursize = op.args[1].getint() - curfields = {} - for i in range(instnode.cursize): - curfields[i] = InstanceNode(valuesource, - const=True) - instnode.curfields = curfields - continue - elif opname == 'append': - instnode = self.nodes[op.args[1]] - valuenode = self.getnode(op.args[2]) - if not instnode.escaped: - ofs = instnode.cursize - instnode.cursize += 1 - self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) - continue - elif opname == 'insert': - instnode = self.nodes[op.args[1]] - if not instnode.escaped: - ofs = self.getsource(op.args[2]).getint() - valuenode = self.nodes[op.args[3]] - self.optimize_insert(instnode, ofs, valuenode, op.args[3]) - continue - elif opname == 'pop': - instnode = self.nodes[op.args[1]] - if not instnode.escaped: - instnode.cursize -= 1 - ofs = instnode.cursize - if self.optimize_getfield(instnode, ofs, op.results[0]): - del instnode.curfields[ofs] - continue - elif opname == 'len' or opname == 'listnonzero': - instnode = self.nodes[op.args[1]] - if instnode.virtual: - continue +## elif opname == 'newlist': +## instnode = self.nodes[op.results[0]] +## assert isinstance(instnode.cls.source, ListDescr) +## if not instnode.escaped: +## instnode.virtual = True +## valuesource = self.getsource(op.args[2]) +## instnode.cursize = op.args[1].getint() +## curfields = {} +## for i in range(instnode.cursize): +## curfields[i] = InstanceNode(valuesource, +## const=True) +## instnode.curfields = curfields +## continue +## elif opname == 'append': +## instnode = self.nodes[op.args[1]] +## valuenode = self.getnode(op.args[2]) +## if not instnode.escaped: +## ofs = instnode.cursize +## instnode.cursize += 1 +## self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) +## continue +## elif opname == 'insert': +## instnode = self.nodes[op.args[1]] +## if not instnode.escaped: +## ofs = self.getsource(op.args[2]).getint() +## valuenode = self.nodes[op.args[3]] +## self.optimize_insert(instnode, ofs, valuenode, op.args[3]) +## continue +## elif opname == 'pop': +## instnode = self.nodes[op.args[1]] +## if not instnode.escaped: +## instnode.cursize -= 1 +## ofs = instnode.cursize +## if self.optimize_getfield(instnode, ofs, op.results[0]): +## del instnode.curfields[ofs] +## continue +## elif opname == 'len' or opname == 'listnonzero': +## instnode = self.nodes[op.args[1]] +## if instnode.virtual: +## continue elif opname == 'setfield_gc': instnode = self.nodes[op.args[0]] valuenode = self.nodes[op.args[2]] ofs = op.args[1].getint() self.optimize_setfield(instnode, ofs, valuenode, op.args[2]) continue - elif opname == 'setitem': - instnode = self.nodes[op.args[1]] - valuenode = self.getnode(op.args[3]) - ofsbox = self.getsource(op.args[2]) - if isinstance(ofsbox, ConstInt): - ofs = ofsbox.getint() - self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) - continue +## elif opname == 'setitem': +## instnode = self.nodes[op.args[1]] +## valuenode = self.getnode(op.args[3]) +## ofsbox = self.getsource(op.args[2]) +## if isinstance(ofsbox, ConstInt): +## ofs = ofsbox.getint() +## self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) +## continue elif opname == 'ooisnull' or opname == 'oononnull': instnode = self.nodes[op.args[0]] if instnode.virtual: @@ -797,12 +802,13 @@ for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): # XXX move to IntanceNode eventually - if (node.cls is not None and - isinstance(node.cls.source, ListDescr)): - newoperations.append(ResOperation('setitem', - [node.cls.source.setfunc, node.source, - ConstInt(ofs), valuenode.source], [])) - else: +## if (node.cls is not None and +## isinstance(node.cls.source, ListDescr)): +## newoperations.append(ResOperation('setitem', +## [node.cls.source.setfunc, node.source, +## ConstInt(ofs), valuenode.source], [])) +## else: + if 1: newoperations.append(ResOperation('setfield_gc', [node.source, ConstInt(ofs), valuenode.source], [])) node.dirtyfields = {} @@ -840,12 +846,12 @@ new_instnode = self.nodes[jump_op.args[i]] old_specnode.adapt_to(new_instnode) -def box_from_index(allocated_boxes, allocated_lists, +def box_from_index(allocated_boxes, ## allocated_lists, boxes_from_frame, index): if index < 0: return boxes_from_frame[~index] - if index > 0xffff: - return allocated_lists[(index - 1) >> 16] +## if index > 0xffff: +## return allocated_lists[(index - 1) >> 16] return allocated_boxes[index] def rebuild_boxes_from_guard_failure(guard_op, metainterp, boxes_from_frame): @@ -861,39 +867,40 @@ [sizebox, vtablebox], 'ptr', False) allocated_boxes.append(instbox) - for malloc_func, lgt in storage.list_allocations: - sizebox = ConstInt(lgt) - [listbox] = history.execute_and_record('newlist', - [malloc_func, sizebox], - 'ptr', False) - allocated_lists.append(listbox) +## for malloc_func, lgt in storage.list_allocations: +## sizebox = ConstInt(lgt) +## [listbox] = history.execute_and_record('newlist', +## [malloc_func, sizebox], +## 'ptr', False) +## allocated_lists.append(listbox) for index_in_alloc, ofs, index_in_arglist in storage.setfields: - fieldbox = box_from_index(allocated_boxes, allocated_lists, + fieldbox = box_from_index(allocated_boxes, ## allocated_lists, boxes_from_frame, index_in_arglist) - box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, + box = box_from_index(allocated_boxes, ## allocated_lists, + boxes_from_frame, index_in_alloc) history.execute_and_record('setfield_gc', [box, ConstInt(ofs), fieldbox], 'void', False) - for setfunc, index_in_alloc, ofs, index_in_arglist in storage.setitems: - itembox = box_from_index(allocated_boxes, allocated_lists, - boxes_from_frame, index_in_arglist) - box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, - index_in_alloc) - history.execute_and_record('setitem', - [setfunc, box, ConstInt(ofs), itembox], - 'void', False) - if storage.setitems: - #history.execute_and_record('guard_no_exception', [], 'void', False) - # XXX this needs to check for exceptions somehow - # create guard_no_excpetion somehow, needs tests - pass +## for setfunc, index_in_alloc, ofs, index_in_arglist in storage.setitems: +## itembox = box_from_index(allocated_boxes, allocated_lists, +## boxes_from_frame, index_in_arglist) +## box = box_from_index(allocated_boxes, allocated_lists, boxes_from_frame, +## index_in_alloc) +## history.execute_and_record('setitem', +## [setfunc, box, ConstInt(ofs), itembox], +## 'void', False) +## if storage.setitems: +## #history.execute_and_record('guard_no_exception', [], 'void', False) +## # XXX this needs to check for exceptions somehow +## # create guard_no_excpetion somehow, needs tests +## pass newboxes = [] for index in storage.indices: if index < 0: newboxes.append(boxes_from_frame[~index]) - elif index > 0xffff: - newboxes.append(allocated_lists[(index - 1) >> 16]) +## elif index > 0xffff: +## newboxes.append(allocated_lists[(index - 1) >> 16]) else: newboxes.append(allocated_boxes[index]) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Feb 24 14:29:31 2009 @@ -8,7 +8,7 @@ from pypy.jit.metainterp import history, support from pypy.jit.metainterp.history import (Const, ConstInt, ConstPtr, Box, - BoxInt, BoxPtr, GuardOp) + BoxInt, BoxPtr, GuardOp, Options) from pypy.jit.metainterp.compile import compile_new_loop, compile_new_bridge from pypy.jit.metainterp.heaptracker import (get_vtable_for_gcstruct, populate_type_cache) @@ -1006,10 +1006,3 @@ class GenerateMergePoint(Exception): def __init__(self, args): self.argboxes = args - - -class Options: - def __init__(self, specialize=True): - self.specialize = specialize - def _freeze_(self): - return True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Tue Feb 24 14:29:31 2009 @@ -26,6 +26,7 @@ return True class SpecNodeWithBox(NotSpecNode): + # XXX what is this class used for? def __init__(self, box): self.box = box @@ -58,14 +59,14 @@ return False return instnode.cls.source.equals(self.known_class) -class FixedListSpecNode(FixedClassSpecNode): +##class FixedListSpecNode(FixedClassSpecNode): - def equals(self, other): - if type(other) is not FixedListSpecNode: - return False - else: - assert isinstance(other, FixedListSpecNode) # make annotator happy - return self.known_class.equals(other.known_class) +## def equals(self, other): +## if type(other) is not FixedListSpecNode: +## return False +## else: +## assert isinstance(other, FixedListSpecNode) # make annotator happy +## return self.known_class.equals(other.known_class) class SpecNodeWithFields(FixedClassSpecNode): def __init__(self, known_class, fields): @@ -160,40 +161,40 @@ [instnode.source, ConstInt(ofs)], [box])) newboxlist.append(box) -class DelayedListSpecNode(DelayedSpecNode): +##class DelayedListSpecNode(DelayedSpecNode): - def expand_boxlist(self, instnode, newboxlist, oplist): - from pypy.jit.metainterp.history import ResOperation, ConstInt - from pypy.jit.metainterp.codewriter import ListDescr +## def expand_boxlist(self, instnode, newboxlist, oplist): +## from pypy.jit.metainterp.history import ResOperation, ConstInt +## from pypy.jit.metainterp.codewriter import ListDescr - newboxlist.append(instnode.source) - for ofs, subspecnode in self.fields: - assert isinstance(subspecnode, SpecNodeWithBox) - if oplist is None: - instnode.cleanfields[ofs] = instnode.origfields[ofs] - newboxlist.append(instnode.curfields[ofs].source) - else: - if ofs in instnode.cleanfields: - newboxlist.append(instnode.cleanfields[ofs].source) - else: - ld = instnode.cls.source - assert isinstance(ld, ListDescr) - box = subspecnode.box.clonebox() - oplist.append(ResOperation('getitem', - [ld.getfunc, instnode.source, ConstInt(ofs)], [box])) - newboxlist.append(box) - - def extract_runtime_data(self, cpu, valuebox, resultlist): - from pypy.jit.metainterp.codewriter import ListDescr - - resultlist.append(valuebox) - ld = self.known_class - assert isinstance(ld, ListDescr) - for ofs, subspecnode in self.fields: - fieldbox = cpu.execute_operation('getitem', - [ld.getfunc, valuebox, ConstInt(ofs)], - ld.tp) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) +## newboxlist.append(instnode.source) +## for ofs, subspecnode in self.fields: +## assert isinstance(subspecnode, SpecNodeWithBox) +## if oplist is None: +## instnode.cleanfields[ofs] = instnode.origfields[ofs] +## newboxlist.append(instnode.curfields[ofs].source) +## else: +## if ofs in instnode.cleanfields: +## newboxlist.append(instnode.cleanfields[ofs].source) +## else: +## ld = instnode.cls.source +## assert isinstance(ld, ListDescr) +## box = subspecnode.box.clonebox() +## oplist.append(ResOperation('getitem', +## [ld.getfunc, instnode.source, ConstInt(ofs)], [box])) +## newboxlist.append(box) + +## def extract_runtime_data(self, cpu, valuebox, resultlist): +## from pypy.jit.metainterp.codewriter import ListDescr + +## resultlist.append(valuebox) +## ld = self.known_class +## assert isinstance(ld, ListDescr) +## for ofs, subspecnode in self.fields: +## fieldbox = cpu.execute_operation('getitem', +## [ld.getfunc, valuebox, ConstInt(ofs)], +## ld.tp) +## subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) class VirtualizableSpecNode(VirtualizedSpecNode): @@ -215,28 +216,28 @@ return False return SpecNodeWithFields.equals(self, other) -class VirtualListSpecNode(VirtualSpecNode): - - def __init__(self, known_class, fields, known_length): - VirtualSpecNode.__init__(self, known_class, fields) - self.known_length = known_length +##class VirtualListSpecNode(VirtualSpecNode): - def mutate_nodes(self, instnode): - VirtualSpecNode.mutate_nodes(self, instnode) - instnode.known_length = self.known_length - - def equals(self, other): - if not isinstance(other, VirtualListSpecNode): - return False - return SpecNodeWithFields.equals(self, other) +## def __init__(self, known_class, fields, known_length): +## VirtualSpecNode.__init__(self, known_class, fields) +## self.known_length = known_length + +## def mutate_nodes(self, instnode): +## VirtualSpecNode.mutate_nodes(self, instnode) +## instnode.known_length = self.known_length + +## def equals(self, other): +## if not isinstance(other, VirtualListSpecNode): +## return False +## return SpecNodeWithFields.equals(self, other) - def extract_runtime_data(self, cpu, valuebox, resultlist): - from pypy.jit.metainterp.codewriter import ListDescr +## def extract_runtime_data(self, cpu, valuebox, resultlist): +## from pypy.jit.metainterp.codewriter import ListDescr - for ofs, subspecnode in self.fields: - cls = self.known_class - assert isinstance(cls, ListDescr) - fieldbox = cpu.execute_operation('getitem', - [cls.getfunc, valuebox, ConstInt(ofs)], - cls.tp) - subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) +## for ofs, subspecnode in self.fields: +## cls = self.known_class +## assert isinstance(cls, ListDescr) +## fieldbox = cpu.execute_operation('getitem', +## [cls.getfunc, valuebox, ConstInt(ofs)], +## cls.tp) +## subspecnode.extract_runtime_data(cpu, fieldbox, resultlist) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Tue Feb 24 14:29:31 2009 @@ -94,15 +94,17 @@ def test_tl_base(self): res = self.meta_interp(self.main.im_func, [0, 6]) + assert res == 5040 + py.test.skip("re-enable list optimizations") self.check_loops({'merge_point':1, 'int_mul':1, 'jump':1, 'int_sub':1, 'int_is_true':1, 'int_le':1, 'guard_false':1}) - assert res == 5040 def test_tl_2(self): res = self.meta_interp(self.main.im_func, [1, 10]) assert res == self.main.im_func(1, 10) + py.test.skip("re-enable list optimizations") self.check_loops({'merge_point':1, 'int_sub':1, 'int_le':1, 'int_is_true':1, 'guard_false':1, 'jump':1}) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vable_optimize.py Tue Feb 24 14:29:31 2009 @@ -14,7 +14,7 @@ from pypy.jit.metainterp.virtualizable import VirtualizableDesc from pypy.jit.metainterp.test.test_optimize import (cpu, NODE, node_vtable, equaloplists, Loop) -from pypy.jit.metainterp.codewriter import ListDescr +#from pypy.jit.metainterp.codewriter import ListDescr # ____________________________________________________________ @@ -201,7 +201,8 @@ # ____________________________________________________________ -class D: +if 0: + class D: class SomeDescr(ListDescr): def __init__(self): pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Tue Feb 24 14:29:31 2009 @@ -1,4 +1,6 @@ import py +py.test.skip("re-enable list optimizations") + from pypy.rlib.jit import JitDriver, hint from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype From arigo at codespeak.net Tue Feb 24 15:11:39 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Feb 2009 15:11:39 +0100 (CET) Subject: [pypy-svn] r62109 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090224141139.BF619168442@codespeak.net> Author: arigo Date: Tue Feb 24 15:11:38 2009 New Revision: 62109 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Re-add the optimization of not including in the liveboxes of guard_false/guard_true the box that is being switched on. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Tue Feb 24 15:11:38 2009 @@ -134,6 +134,9 @@ def _getrepr_(self): return self.value +CONST_FALSE = ConstInt(0) +CONST_TRUE = ConstInt(1) + class ConstAddr(Const): # only for constants built before translation type = 'int' ever_seen = False Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Tue Feb 24 15:11:38 2009 @@ -263,11 +263,14 @@ currentpc = self.pc targetpc = target opname = "guard_true" + const_if_fail = history.CONST_FALSE else: currentpc = target targetpc = self.pc opname = "guard_false" - self.generate_guard(targetpc, opname, box, ignore_box=switchcase) + const_if_fail = history.CONST_TRUE + self.generate_guard(targetpc, opname, box, ignore_box=box, + const_if_fail=const_if_fail) self.pc = currentpc @arguments("orgpc", "box", "intargs", "jumptargets") @@ -575,7 +578,8 @@ if stop: break - def generate_guard(self, pc, opname, box, extraargs=[], ignore_box=None): + def generate_guard(self, pc, opname, box, extraargs=[], ignore_box=None, + const_if_fail=None): if isinstance(box, Const): # no need for a guard return if isinstance(self.metainterp.history, history.BlackHole): @@ -583,8 +587,12 @@ liveboxes = [] for frame in self.metainterp.framestack: for framebox in frame.env: + assert framebox is not None if framebox is not ignore_box: liveboxes.append(framebox) + else: + assert const_if_fail is not None + liveboxes.append(const_if_fail) if box is not None: extraargs = [box] + extraargs guard_op = self.metainterp.history.record(opname, extraargs, [], From arigo at codespeak.net Tue Feb 24 16:35:58 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Feb 2009 16:35:58 +0100 (CET) Subject: [pypy-svn] r62114 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090224153558.72086168442@codespeak.net> Author: arigo Date: Tue Feb 24 16:35:58 2009 New Revision: 62114 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: More commenting out (all temporary), and simplify a few variables away. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Feb 24 16:35:58 2009 @@ -38,7 +38,7 @@ ## self.list_allocations = [] ## self.setitems = [] - def deal_with_box(self, box, nodes, liveboxes, memo, ready): + def deal_with_box(self, box, nodes, liveboxes, memo): if isinstance(box, Const) or box not in nodes: virtual = False virtualized = False @@ -67,8 +67,7 @@ res = alloc_offset memo[box] = res for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo, - ready) + num = self.deal_with_box(node.source, nodes, liveboxes, memo) ## if isinstance(instnode.cls.source, ListDescr): ## ld = instnode.cls.source ## x = (alloc_offset + 1) << 16 @@ -82,8 +81,7 @@ memo[box] = res liveboxes.append(box) for ofs, node in instnode.curfields.items(): - num = self.deal_with_box(node.source, nodes, liveboxes, memo, - ready) + num = self.deal_with_box(node.source, nodes, liveboxes, memo) self.setfields.append((res, ofs, num)) else: res = ~len(liveboxes) @@ -107,8 +105,8 @@ self.cleanfields = {} self.dirtyfields = {} self.expanded_fields = {} - self.origsize = -1 - self.cursize = -1 + #self.origsize = -1 + #self.cursize = -1 def escape_if_startbox(self, memo): if self in memo: @@ -283,13 +281,13 @@ 1): ##not isinstance(instnode.cls.source, ListDescr)): instnode.expanded_fields[field] = None - def find_nodes_insert(self, instnode, field, fieldnode): - for ofs, node in instnode.curfields.items(): - if ofs >= field: - instnode.curfields[ofs + 1] = node - instnode.curfields[field] = fieldnode - instnode.cursize += 1 - self.dependency_graph.append((instnode, fieldnode)) +## def find_nodes_insert(self, instnode, field, fieldnode): +## for ofs, node in instnode.curfields.items(): +## if ofs >= field: +## instnode.curfields[ofs + 1] = node +## instnode.curfields[field] = fieldnode +## instnode.cursize += 1 +## self.dependency_graph.append((instnode, fieldnode)) def find_nodes(self): # Steps (1) and (2) @@ -515,8 +513,7 @@ op = op.clone() for box in old_boxes: indices.append(storage.deal_with_box(box, self.nodes, - liveboxes, memo, - self.ready_results)) + liveboxes, memo)) rev_boxes = {} for i in range(len(liveboxes)): box = liveboxes[i] @@ -555,7 +552,7 @@ instnode = self.nodes[box] assert not instnode.virtual box = instnode.source - assert isinstance(box, Const) or box in self.ready_results + #assert isinstance(box, Const) or box in self.ready_results newboxes.append(box) return newboxes @@ -566,8 +563,8 @@ def optimize_getfield(self, instnode, ofs, box): if instnode.virtual or instnode.virtualized: - if ofs < 0: - ofs = instnode.cursize + ofs +## if ofs < 0: +## ofs = instnode.cursize + ofs assert ofs in instnode.curfields return True # this means field is never actually elif ofs in instnode.cleanfields: @@ -579,8 +576,8 @@ def optimize_setfield(self, instnode, ofs, valuenode, valuebox): if instnode.virtual or instnode.virtualized: - if ofs < 0: - ofs = instnode.cursize + ofs +## if ofs < 0: +## ofs = instnode.cursize + ofs instnode.curfields[ofs] = valuenode else: assert not valuenode.virtual @@ -588,19 +585,19 @@ instnode.dirtyfields[ofs] = self.nodes[valuebox] # we never perform this operation here, note - def optimize_insert(self, instnode, field, valuenode, valuebox): - assert instnode.virtual - for ofs, node in instnode.curfields.items(): - if ofs >= field: - instnode.curfields[ofs + 1] = node - instnode.curfields[field] = valuenode - instnode.cursize += 1 +## def optimize_insert(self, instnode, field, valuenode, valuebox): +## assert instnode.virtual +## for ofs, node in instnode.curfields.items(): +## if ofs >= field: +## instnode.curfields[ofs + 1] = node +## instnode.curfields[field] = valuenode +## instnode.cursize += 1 def optimize_loop(self): - self.ready_results = {} + #self.ready_results = {} newoperations = [] exception_might_have_happened = False - ops_so_far = [] + #ops_so_far = [] mp = self.loop.operations[0] if mp.opname == 'merge_point': assert len(mp.args) == len(self.specnodes) @@ -614,21 +611,21 @@ assert not self.nodes[box].virtual for op in self.loop.operations: - ops_so_far.append(op) + #ops_so_far.append(op) - if newoperations and newoperations[-1].results: - self.ready_results[newoperations[-1].results[0]] = None + #if newoperations and newoperations[-1].results: + # self.ready_results[newoperations[-1].results[0]] = None opname = op.opname if opname == 'merge_point': args = self.expanded_version_of(op.args, None) op = MergePoint('merge_point', args, []) newoperations.append(op) - for arg in op.args: - self.ready_results[arg] = None + #for arg in op.args: + # self.ready_results[arg] = None continue - elif opname == 'catch': - for arg in op.args: - self.ready_results[arg] = None + #elif opname == 'catch': + # for arg in op.args: + # self.ready_results[arg] = None elif opname == 'jump': args = self.expanded_version_of(op.args, newoperations) self.cleanup_field_caches(newoperations) @@ -643,19 +640,19 @@ op = self.optimize_guard(op) newoperations.append(op) continue - elif opname == 'guard_builtin': - instnode = self.nodes[op.args[0]] - if instnode.cls is None: - instnode.cls = InstanceNode(op.args[1]) - continue - elif opname == 'guard_len': - # it should be completely gone, because if it escapes - # we don't virtualize it anymore - instnode = self.nodes[op.args[0]] - if not instnode.escaped and instnode.cursize == -1: - instnode = self.nodes[op.args[0]] - instnode.cursize = op.args[1].getint() - continue +## elif opname == 'guard_builtin': +## instnode = self.nodes[op.args[0]] +## if instnode.cls is None: +## instnode.cls = InstanceNode(op.args[1]) +## continue +## elif opname == 'guard_len': +## # it should be completely gone, because if it escapes +## # we don't virtualize it anymore +## instnode = self.nodes[op.args[0]] +## if not instnode.escaped and instnode.cursize == -1: +## instnode = self.nodes[op.args[0]] +## instnode.cursize = op.args[1].getint() +## continue elif opname == 'guard_nonvirtualized': instnode = self.nodes[op.args[0]] if instnode.virtualized or instnode.virtual: From arigo at codespeak.net Tue Feb 24 16:37:12 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Feb 2009 16:37:12 +0100 (CET) Subject: [pypy-svn] r62115 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090224153712.BC3FC168445@codespeak.net> Author: arigo Date: Tue Feb 24 16:37:12 2009 New Revision: 62115 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: There are two classes M in this file :-( Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Tue Feb 24 16:37:12 2009 @@ -695,18 +695,18 @@ spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [L.sum, L.n1, L.v], []), - ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), - ResOperation('int_add', [L.sum, L.v], [L.sum2]), - ResOperation('escape', [L.n1], []), - ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], [ANY]), - Jump('jump', [L.sum2, L.n1, ANY], []), + MergePoint('merge_point', [M.sum, M.n1, M.v], []), + ResOperation('int_sub', [M.v, ConstInt(1)], [M.v2]), + ResOperation('int_add', [M.sum, M.v], [M.sum2]), + ResOperation('escape', [M.n1], []), + ResOperation('getfield_gc', [M.n1, ConstInt(M.ofs_value)], [ANY]), + Jump('jump', [M.sum2, M.n1, ANY], []), ]) # ____________________________________________________________ -class M: +class N: locals().update(A.__dict__) # :-) sum3 = BoxInt(3) v3 = BoxInt(4) @@ -721,16 +721,16 @@ Jump('jump', [sum2, n1], []), ] -def test_M_optimize_loop(): - spec = PerfectSpecializer(Loop(M.ops)) +def test_N_optimize_loop(): + spec = PerfectSpecializer(Loop(N.ops)) spec.find_nodes() spec.intersect_input_and_output() spec.optimize_loop() equaloplists(spec.loop.operations, [ - MergePoint('merge_point', [L.sum, L.n1, L.v], []), - ResOperation('int_sub', [L.v, ConstInt(1)], [L.v2]), - ResOperation('int_add', [L.sum, L.v], [L.sum2]), - ResOperation('escape', [L.n1], []), - ResOperation('getfield_gc', [L.n1, ConstInt(L.ofs_value)], [ANY]), - Jump('jump', [L.sum2, L.n1, ANY], []), + MergePoint('merge_point', [N.sum, N.n1, N.v], []), + ResOperation('int_sub', [N.v, ConstInt(1)], [N.v2]), + ResOperation('int_add', [N.sum, N.v], [N.sum2]), + ResOperation('escape', [N.n1], []), + ResOperation('getfield_gc', [N.n1, ConstInt(N.ofs_value)], [ANY]), + Jump('jump', [N.sum2, N.n1, ANY], []), ]) From arigo at codespeak.net Tue Feb 24 16:44:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Feb 2009 16:44:45 +0100 (CET) Subject: [pypy-svn] r62116 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090224154445.F3105168477@codespeak.net> Author: arigo Date: Tue Feb 24 16:44:45 2009 New Revision: 62116 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Oooups. Typo in the optimization of 'oois' meant that it was removed in bogus cases. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Feb 24 16:44:45 2009 @@ -761,7 +761,7 @@ elif opname == 'oois' or opname == 'ooisnot': instnode_x = self.nodes[op.args[0]] instnode_y = self.nodes[op.args[1]] - if not instnode_x.virtual or not instnode_y.virtual: + if instnode_x.virtual or instnode_y.virtual: box = op.results[0] instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Tue Feb 24 16:44:45 2009 @@ -400,6 +400,31 @@ Jump('jump', [F.sum2, F.v2, F.n3], []), ]) +class F2: + locals().update(A.__dict__) # :-) + node2 = lltype.malloc(NODE) + node3 = lltype.malloc(NODE) + node4 = lltype.malloc(NODE) + n2 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node2)) + n3 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node3)) + n4 = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, node4)) + vbool1 = BoxInt(0) + ops = [ + MergePoint('merge_point', [n2, n3], []), + ResOperation('oois', [n2, n3], [vbool1]), + GuardOp('guard_true', [vbool1], []), + ResOperation('external', [], [n4]), + Jump('jump', [n2, n4], []), + ] + ops[2].liveboxes = [n2] + +def test_F2_optimize_loop(): + spec = PerfectSpecializer(Loop(F2.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, F2.ops) + # ____________________________________________________________ class G: From arigo at codespeak.net Tue Feb 24 17:14:49 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Feb 2009 17:14:49 +0100 (CET) Subject: [pypy-svn] r62118 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090224161449.78DA9168504@codespeak.net> Author: arigo Date: Tue Feb 24 17:14:48 2009 New Revision: 62118 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Replace the non-RPythonic lst.sort() with a simple quicksort. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Feb 24 17:14:48 2009 @@ -153,9 +153,10 @@ d.update(self.origfields) else: d = other.curfields - lst = d.items() - lst.sort() - for ofs, node in lst: + lst = d.keys() + sort_integers(lst) + for ofs in lst: + node = d[ofs] if ofs in self.origfields: specnode = self.origfields[ofs].intersect(node) else: @@ -169,7 +170,7 @@ if not other.virtualized and self.expanded_fields: fields = [] lst = self.expanded_fields.keys() - lst.sort() + sort_integers(lst) for ofs in lst: specnode = SpecNodeWithBox(self.origfields[ofs].source) fields.append((ofs, specnode)) @@ -181,7 +182,7 @@ d = self.origfields.copy() d.update(other.curfields) offsets = d.keys() - offsets.sort() + sort_integers(offsets) fields = [] for ofs in offsets: if ofs in self.origfields and ofs in other.curfields: @@ -798,7 +799,7 @@ # we need to invalidate everything for node in self.nodes.values(): for ofs, valuenode in node.dirtyfields.items(): - # XXX move to IntanceNode eventually + # XXX move to InstanceNode eventually ## if (node.cls is not None and ## isinstance(node.cls.source, ListDescr)): ## newoperations.append(ResOperation('setitem', @@ -902,3 +903,25 @@ newboxes.append(allocated_boxes[index]) return newboxes + + +def partition(array, left, right): + pivot = array[right] + storeindex = left + for i in range(left, right): + if array[i] <= pivot: + array[i], array[storeindex] = array[storeindex], array[i] + storeindex += 1 + # Move pivot to its final place + array[storeindex], array[right] = pivot, array[storeindex] + return storeindex + +def quicksort(array, left, right): + # sort array[left:right+1] (i.e. bounds included) + if right > left: + pivotnewindex = partition(array, left, right) + quicksort(array, left, pivotnewindex - 1) + quicksort(array, pivotnewindex + 1, right) + +def sort_integers(lst): + quicksort(lst, 0, len(lst)-1) From tverwaes at codespeak.net Tue Feb 24 18:01:19 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 24 Feb 2009 18:01:19 +0100 (CET) Subject: [pypy-svn] r62120 - pypy/trunk/pypy/lang/smalltalk Message-ID: <20090224170119.D36DF1684E6@codespeak.net> Author: tverwaes Date: Tue Feb 24 18:01:15 2009 New Revision: 62120 Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py Log: making it a bit more sane. we still have to fix 0<<(too big) cases. Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/primitives.py (original) +++ pypy/trunk/pypy/lang/smalltalk/primitives.py Tue Feb 24 18:01:15 2009 @@ -183,7 +183,7 @@ raise PrimitiveFailedError() return interp.space.wrap_int(receiver // argument) -# #// -- return the result of a division, rounded towards negative infinity +# #// -- return the result of a division, rounded towards negative infinite @expose_primitive(QUO, unwrap_spec=[int, int]) def func(interp, receiver, argument): if argument == 0: @@ -194,11 +194,26 @@ @expose_primitive(BIT_SHIFT, unwrap_spec=[int, int]) def func(interp, receiver, argument): - # left shift, must fail if we loose bits beyond 32 + # TODO: 1 << 100 will overflow to 0. Catch this gracefully by Primitive + # Failing! Use ovfcheck_lfshift + # (http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#integer-types) + + # left shift, must fail if we lose bits beyond 32 if argument > 0: shifted = receiver << argument - if (shifted >> argument) != receiver: - raise PrimitiveFailedError() + + # Make sure we respect our bitlimits set by TAGGED_XXXINT. + if shifted < 0: + # If negative, check if there are no bits unset outside the MAXINT + # region + if constants.TAGGED_MININT ^ shifted > constants.TAGGED_MAXINT: + raise PrimitiveFailedError() + else: + # If possitive, check if there are no bits set outside the MAXINT + # region + if shifted & constants.TAGGED_MAXINT != shifted: + raise PrimitiveFailedError() + return interp.space.wrap_int(shifted) # right shift, ok to lose bits From arigo at codespeak.net Tue Feb 24 18:05:57 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 24 Feb 2009 18:05:57 +0100 (CET) Subject: [pypy-svn] r62121 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp Message-ID: <20090224170557.BD2011684D9@codespeak.net> Author: arigo Date: Tue Feb 24 18:05:56 2009 New Revision: 62121 Removed: pypy/branch/pyjitpl5/pypy/jit/metainterp/rpyjitpl.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: The first translation test passes. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Tue Feb 24 18:05:56 2009 @@ -139,7 +139,6 @@ return history.BoxPtr(llimpl.frame_ptr_getresult(frame)) else: return None - execute_operation._annspecialcase_ = 'specialize:arg(3)' def get_compiled_single_op(self, opname, valueboxes, result_type): keylist = self.compiled_single_ops.setdefault((opname, result_type), Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Tue Feb 24 18:05:56 2009 @@ -441,9 +441,16 @@ execute_and_record._annspecialcase_ = 'specialize:arg(3, 4)' def record(self, opname, argboxes, resboxes, opcls=ResOperation): + # xxx the indirection from record to _record is to work + # around a limitation of the annotator (normalizecalls.py) + return self._record(opname, argboxes, resboxes, opcls) + record._annspecialcase_ = 'specialize:arg(4)' + + def _record(self, opname, argboxes, resboxes, opcls): op = opcls(opname, argboxes, resboxes) self.operations.append(op) return op + _record._annspecialcase_ = 'specialize:arg(4)' def generate_anything_since(self, old_index): return len(self.operations) > old_index @@ -452,8 +459,9 @@ pass class BlackHole(RunningMatcher): - def record(self, step, argboxes, resboxes, opcls=ResOperation): + def _record(self, step, argboxes, resboxes, opcls): return None + _record._annspecialcase_ = 'specialize:arg(4)' def generate_anything_since(self, old_index): return True Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Tue Feb 24 18:05:56 2009 @@ -297,9 +297,13 @@ for box in self.loop.operations[0].args: self.nodes[box] = InstanceNode(box, escaped=False, startbox=True, const=isinstance(box, Const)) - for op in self.loop.operations[1:-1]: + for op in self.loop.operations: opname = op.opname - if opname == 'new_with_vtable': + if (opname == 'merge_point' or + opname == 'catch' or + opname == 'jump'): + continue + elif opname == 'new_with_vtable': box = op.results[0] instnode = InstanceNode(box, escaped=False) instnode.cls = InstanceNode(op.args[1], const=True) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Tue Feb 24 18:05:56 2009 @@ -3,6 +3,7 @@ from pypy.rpython import rlist from pypy.rpython.lltypesystem import rdict, rstr from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython.extregistry import ExtRegistryEntry from pypy.translator.simplify import get_funcobj from pypy.translator.unsimplify import split_block from pypy.objspace.flow.model import Constant @@ -80,6 +81,14 @@ return fnptr._callable(*args) return on_top_of_llinterp +class Entry(ExtRegistryEntry): + _about_ = maybe_on_top_of_llinterp + def compute_result_annotation(self, s_rtyper, s_fnptr): + return s_fnptr + def specialize_call(self, hop): + hop.exception_cannot_occur() + return hop.inputarg(hop.args_r[1], arg=1) + # ____________________________________________________________ # # Manually map oopspec'ed operations back to their ll implementation Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Tue Feb 24 18:05:56 2009 @@ -29,17 +29,10 @@ warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests return interp.eval_graph(graph, args) -def rpython_ll_meta_interp(function, args, loops=None, **kwds): - kwds['translate_support_code'] = True - interp, graph = get_interpreter(function, args, backendopt=True, - inline_threshold=0) - clear_tcache() - translator = interp.typer.annotator.translator - warmrunnerdesc = WarmRunnerDesc(translator, **kwds) - warmrunnerdesc.state.set_param_threshold(3) # for tests - warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests - xxx - interp.eval_graph(boot, args) +def rpython_ll_meta_interp(function, args, loops='not used right now', **kwds): + return ll_meta_interp(function, args, + translate_support_code=True, backendopt=True, + **kwds) def find_can_enter_jit(graphs): results = [] @@ -93,6 +86,8 @@ self.rewrite_jit_merge_point() self.metainterp.num_green_args = self.num_green_args self.metainterp.state = self.state + if self.cpu.translate_support_code: + self.annhelper.finish() def _freeze_(self): return True @@ -250,42 +245,45 @@ self.metainterp.ExitFrameWithException = ExitFrameWithException self.metainterp.ContinueRunningNormally = ContinueRunningNormally rtyper = self.translator.rtyper + portalfunc_ARGS = unrolling_iterable(list(enumerate(PORTALFUNC.ARGS))) + RESULT = PORTALFUNC.RESULT - if not self.cpu.translate_support_code: - def ll_portal_runner(*args): - while 1: - try: - return support.maybe_on_top_of_llinterp(rtyper, - portal_ptr)(*args) - except ContinueRunningNormally, e: - args = [] - for i, arg in enumerate(e.args): - v = arg.value - # HACK for x86 backend always returning int - if (isinstance(PORTALFUNC.ARGS[i], lltype.Ptr) and - isinstance(v, int)): - v = self.metainterp.cpu.cast_int_to_gcref(v) - if lltype.typeOf(v) == llmemory.GCREF: - v = lltype.cast_opaque_ptr(PORTALFUNC.ARGS[i], - v) - args.append(v) - except DoneWithThisFrame, e: - if e.resultbox is not None: - return e.resultbox.value - return - except ExitFrameWithException, e: + def unwrap(TYPE, box): + if TYPE is lltype.Void: + return None + if isinstance(TYPE, lltype.Ptr): + return box.getptr(TYPE) + else: + return box.getint() + unwrap._annspecialcase_ = 'specialize:arg(0)' + + def ll_portal_runner(*args): + while 1: + try: + return support.maybe_on_top_of_llinterp(rtyper, + portal_ptr)(*args) + except ContinueRunningNormally, e: + args = () + for i, ARG in portalfunc_ARGS: + v = unwrap(ARG, e.args[i]) + # HACK for x86 backend always returning int + #if isinstance(ARG, lltype.Ptr) and type(v) is int: + # v = self.metainterp.cpu.cast_int_to_gcref(v) + #if lltype.typeOf(v) == llmemory.GCREF: + # v = lltype.cast_opaque_ptr(ARG, v) + args = args + (v,) + except DoneWithThisFrame, e: + return unwrap(RESULT, e.resultbox) + except ExitFrameWithException, e: + value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT)) + if we_are_translated(): + # re-raise the exception as it is + raise Exception, value + else: type = e.typebox.getaddr(self.metainterp.cpu) type = llmemory.cast_adr_to_ptr(type, rclass.CLASSTYPE) - value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT)) raise LLException(type, value) - else: - def ll_portal_runner(*args): - while 1: - #try: - portal_ptr(*args) - #xexcept DoneWi - portal_runner_ptr = self.helper_func(lltype.Ptr(PORTALFUNC), ll_portal_runner) @@ -308,8 +306,6 @@ origblock.exitswitch = None origblock.recloseblock(Link([v_result], origportalgraph.returnblock)) checkgraph(origportalgraph) - if self.cpu.translate_support_code: - self.annhelper.finish() def decode_hp_hint_args(op): From tverwaes at codespeak.net Wed Feb 25 11:03:45 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 25 Feb 2009 11:03:45 +0100 (CET) Subject: [pypy-svn] r62130 - pypy/trunk/pypy/translator/goal Message-ID: <20090225100345.6FCEC168443@codespeak.net> Author: tverwaes Date: Wed Feb 25 11:03:41 2009 New Revision: 62130 Modified: pypy/trunk/pypy/translator/goal/targetimageloadingsmalltalk.py pypy/trunk/pypy/translator/goal/targettinybenchsmalltalk.py Log: updating the targets to work with the new version of the objspace. targetimageloadingsmalltalk fails from a bug in pypy as far as I can tell... Modified: pypy/trunk/pypy/translator/goal/targetimageloadingsmalltalk.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetimageloadingsmalltalk.py (original) +++ pypy/trunk/pypy/translator/goal/targetimageloadingsmalltalk.py Wed Feb 25 11:03:41 2009 @@ -2,25 +2,21 @@ import sys import os from pypy.lang.smalltalk import model, interpreter, primitives, shadow -from pypy.lang.smalltalk import objtable -from pypy.lang.smalltalk import classtable +# from pypy.lang.smalltalk import classtable # from pypy.lang.smalltalk.test.test_interpreter import * from pypy.lang.smalltalk import squeakimage from pypy.lang.smalltalk import constants -mockclass = classtable.bootstrap_class - -def tinyBenchmarks(image): - interp = interpreter.Interpreter() +def tinyBenchmarks(space, image): + interp = interpreter.Interpreter(space) w_object = model.W_SmallInteger(0) - # Should get this from w_object - s_class = w_object.shadow_of_my_class() + s_class = w_object.shadow_of_my_class(space) w_method = s_class.lookup("tinyBenchmarks") assert w_method - w_frame = w_method.create_frame(w_object, []) + w_frame = w_method.create_frame(space, w_object, []) interp.store_w_active_context(w_frame) counter = 0 @@ -51,11 +47,13 @@ else: print "usage:", argv[0], "" return -1 - reader = squeakimage.ImageReader(squeakimage.Stream(DummyFile(filename))) + from pypy.lang.smalltalk import objspace + space = objspace.ObjSpace() + reader = squeakimage.ImageReader(space, squeakimage.Stream(DummyFile(filename))) reader.initialize() image = squeakimage.SqueakImage() - image.from_reader(reader) - interp = tinyBenchmarks(image) + image.from_reader(space, reader) + interp = tinyBenchmarks(space, image) run_benchmarks(interp) return 0 Modified: pypy/trunk/pypy/translator/goal/targettinybenchsmalltalk.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targettinybenchsmalltalk.py (original) +++ pypy/trunk/pypy/translator/goal/targettinybenchsmalltalk.py Wed Feb 25 11:03:41 2009 @@ -22,8 +22,6 @@ w_object = model.W_SmallInteger(0) - # Should get this from w_object - w_smallint_class = image.special(constants.SO_SMALLINTEGER_CLASS) s_class = w_object.shadow_of_my_class(space) w_method = s_class.lookup("tinyBenchmarks") From tverwaes at codespeak.net Wed Feb 25 11:05:02 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 25 Feb 2009 11:05:02 +0100 (CET) Subject: [pypy-svn] r62131 - pypy/trunk/pypy/lang/smalltalk Message-ID: <20090225100502.64A201683FF@codespeak.net> Author: tverwaes Date: Wed Feb 25 11:05:01 2009 New Revision: 62131 Modified: pypy/trunk/pypy/lang/smalltalk/constants.py pypy/trunk/pypy/lang/smalltalk/model.py pypy/trunk/pypy/lang/smalltalk/objspace.py pypy/trunk/pypy/lang/smalltalk/primitives.py pypy/trunk/pypy/lang/smalltalk/shadow.py Log: switching from space.w_[class] to space.classtable['w_class'] since those w_... are not initialized at compiletime in the new objspace setting. Also moved around all subfunctions in objspace for exactly the same reason. Modified: pypy/trunk/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/constants.py (original) +++ pypy/trunk/pypy/lang/smalltalk/constants.py Wed Feb 25 11:05:01 2009 @@ -131,5 +131,8 @@ "smalltalkdict" : SO_SMALLTALK, } -TAGGED_MAXINT = 2 ** (LONG_BIT - 2) - 1 -TAGGED_MININT = -2 ** (LONG_BIT - 2) +BITS = 32 +# Above should become: +# BITS = LONG_BIT +TAGGED_MAXINT = 2 ** (BITS - 2) - 1 +TAGGED_MININT = -2 ** (BITS - 2) Modified: pypy/trunk/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/model.py (original) +++ pypy/trunk/pypy/lang/smalltalk/model.py Wed Feb 25 11:05:01 2009 @@ -106,7 +106,7 @@ def getclass(self, space): """Return SmallInteger from special objects array.""" - return space.w_SmallInteger + return space.classtable['w_SmallInteger'] def gethash(self): return self.value @@ -142,7 +142,7 @@ def getclass(self, space): """Return Float from special objects array.""" - return space.w_Float + return space.classtable['w_Float'] def gethash(self): return 41 # XXX check this @@ -202,7 +202,8 @@ Float).""" def __init__(self, w_class): - if w_class is not None: # it's None only for testing + if w_class is not None: # it's None for testing and bootstrapping the + # class hierarchy assert isinstance(w_class, W_PointersObject) self.w_class = w_class @@ -218,7 +219,9 @@ return self._shadow.getname() else: name = None - if self.w_class._shadow is not None: + if (hasattr(self, 'w_class') and + self.w_class is not None and + self.w_class._shadow is not None): name = self.w_class._shadow.name return "a %s" % (name or '?',) @@ -407,11 +410,12 @@ def atput0(self, space, index0, w_value): if isinstance(w_value, W_BytesObject): + # TODO: Completely untested! This failed translation bigtime... # XXX Probably we want to allow all subclasses - if not (w_value.getclass(self).is_same_object( + if not (w_value.getclass(space).is_same_object( space.classtable['w_LargePositiveInteger']) and w_value.size() == 4): - raise UnwrappingError("Failed to convert bytes to word") + raise error.UnwrappingError("Failed to convert bytes to word") word = 0 for i in range(4): word += ord(w_value.getchar(i)) << 8*i @@ -473,7 +477,7 @@ return self.w_compiledin def getclass(self, space): - return space.w_CompiledMethod + return space.classtable['w_CompiledMethod'] def getliteral(self, index): # We changed this part Modified: pypy/trunk/pypy/lang/smalltalk/objspace.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/objspace.py (original) +++ pypy/trunk/pypy/lang/smalltalk/objspace.py Wed Feb 25 11:05:01 2009 @@ -10,16 +10,36 @@ self.make_bootstrap_classes() self.make_bootstrap_objects() + def define_core_cls(self, name, w_superclass, w_metaclass): + assert name.startswith('w_') + w_class = bootstrap_class(self, instsize=0, # XXX + w_superclass=w_superclass, + w_metaclass=w_metaclass, + name=name[2:]) + self.classtable[name] = w_class + return w_class + + def define_cls(self, cls_nm, supercls_nm, instvarsize=0, + format=shadow.POINTERS, varsized=False): + assert cls_nm.startswith("w_") + meta_nm = cls_nm + "Class" + meta_super_nm = supercls_nm + "Class" + w_Metaclass = self.classtable["w_Metaclass"] + w_meta_cls = self.classtable[meta_nm] = \ + bootstrap_class(self, 0, # XXX + self.classtable[meta_super_nm], + w_Metaclass, + name=meta_nm[2:]) + w_cls = self.classtable[cls_nm] = \ + bootstrap_class(self, instvarsize, + self.classtable[supercls_nm], + w_meta_cls, + format=format, + varsized=varsized, + name=cls_nm[2:]) + + def make_bootstrap_classes(self): - def define_core_cls(name, w_superclass, w_metaclass): - assert name.startswith('w_') - w_class = bootstrap_class(self, instsize=0, # XXX - w_superclass=w_superclass, - w_metaclass=w_metaclass, - name=name[2:]) - self.classtable[name] = w_class - return w_class - # A complete minimal setup (including Behavior) would look like this # # class: superclass: metaclass: @@ -43,14 +63,14 @@ ["w_Class", "w_ClassDescription"], ["w_Metaclass", "w_ClassDescription"], ] - define_core_cls("w_ProtoObjectClass", None, None) - w_ProtoObjectClass = self.classtable["w_ProtoObjectClass"] - define_core_cls("w_ProtoObject", None, w_ProtoObjectClass) + w_ProtoObjectClass = self.define_core_cls("w_ProtoObjectClass", None, None) + # w_ProtoObjectClass = self.classtable["w_ProtoObjectClass"] + self.define_core_cls("w_ProtoObject", None, w_ProtoObjectClass) for (cls_nm, super_cls_nm) in cls_nm_tbl: meta_nm = cls_nm + "Class" meta_super_nm = super_cls_nm + "Class" - w_metacls = define_core_cls(meta_nm, self.classtable[meta_super_nm], None) - define_core_cls(cls_nm, self.classtable[super_cls_nm], w_metacls) + w_metacls = self.define_core_cls(meta_nm, self.classtable[meta_super_nm], None) + self.define_core_cls(cls_nm, self.classtable[super_cls_nm], w_metacls) w_Class = self.classtable["w_Class"] w_Metaclass = self.classtable["w_Metaclass"] # XXX @@ -65,71 +85,53 @@ if w_cls_obj.w_class is None: w_cls_obj.w_class = w_Metaclass - def define_cls(cls_nm, supercls_nm, instvarsize=0, format=shadow.POINTERS, - varsized=False): - assert cls_nm.startswith("w_") - meta_nm = cls_nm + "Class" - meta_super_nm = supercls_nm + "Class" - w_Metaclass = self.classtable["w_Metaclass"] - w_meta_cls = self.classtable[meta_nm] = \ - bootstrap_class(self, 0, # XXX - self.classtable[meta_super_nm], - w_Metaclass, - name=meta_nm[2:]) - w_cls = self.classtable[cls_nm] = \ - bootstrap_class(self, instvarsize, - self.classtable[supercls_nm], - w_meta_cls, - format=format, - varsized=varsized, - name=cls_nm[2:]) - - define_cls("w_Magnitude", "w_Object") - define_cls("w_Character", "w_Magnitude", instvarsize=1) - define_cls("w_Number", "w_Magnitude") - define_cls("w_Integer", "w_Number") - define_cls("w_SmallInteger", "w_Integer") - define_cls("w_LargePositiveInteger", "w_Integer", format=shadow.BYTES) - define_cls("w_Float", "w_Number", format=shadow.BYTES) - define_cls("w_Collection", "w_Object") - define_cls("w_SequenceableCollection", "w_Collection") - define_cls("w_ArrayedCollection", "w_SequenceableCollection") - define_cls("w_Array", "w_ArrayedCollection", varsized=True) - define_cls("w_String", "w_ArrayedCollection", format=shadow.BYTES) - define_cls("w_UndefinedObject", "w_Object") - define_cls("w_Boolean", "w_Object") - define_cls("w_True", "w_Boolean") - define_cls("w_False", "w_Boolean") - define_cls("w_ByteArray", "w_ArrayedCollection", format=shadow.BYTES) - define_cls("w_MethodDict", "w_Object", instvarsize=2, varsized=True) - define_cls("w_CompiledMethod", "w_ByteArray", format=shadow.COMPILED_METHOD) - define_cls("w_ContextPart", "w_Object") - define_cls("w_MethodContext", "w_ContextPart") - define_cls("w_Link", "w_Object") - define_cls("w_Process", "w_Link") - define_cls("w_Point", "w_Object") - define_cls("w_LinkedList", "w_SequenceableCollection") - define_cls("w_Semaphore", "w_LinkedList") - define_cls("w_BlockContext", "w_ContextPart", + self.define_cls("w_Magnitude", "w_Object") + self.define_cls("w_Character", "w_Magnitude", instvarsize=1) + self.define_cls("w_Number", "w_Magnitude") + self.define_cls("w_Integer", "w_Number") + self.define_cls("w_SmallInteger", "w_Integer") + self.define_cls("w_LargePositiveInteger", "w_Integer", format=shadow.BYTES) + self.define_cls("w_Float", "w_Number", format=shadow.BYTES) + self.define_cls("w_Collection", "w_Object") + self.define_cls("w_SequenceableCollection", "w_Collection") + self.define_cls("w_ArrayedCollection", "w_SequenceableCollection") + self.define_cls("w_Array", "w_ArrayedCollection", varsized=True) + self.define_cls("w_String", "w_ArrayedCollection", format=shadow.BYTES) + self.define_cls("w_UndefinedObject", "w_Object") + self.define_cls("w_Boolean", "w_Object") + self.define_cls("w_True", "w_Boolean") + self.define_cls("w_False", "w_Boolean") + self.define_cls("w_ByteArray", "w_ArrayedCollection", format=shadow.BYTES) + self.define_cls("w_MethodDict", "w_Object", instvarsize=2, varsized=True) + self.define_cls("w_CompiledMethod", "w_ByteArray", format=shadow.COMPILED_METHOD) + self.define_cls("w_ContextPart", "w_Object") + self.define_cls("w_MethodContext", "w_ContextPart") + self.define_cls("w_Link", "w_Object") + self.define_cls("w_Process", "w_Link") + self.define_cls("w_Point", "w_Object") + self.define_cls("w_LinkedList", "w_SequenceableCollection") + self.define_cls("w_Semaphore", "w_LinkedList") + self.define_cls("w_BlockContext", "w_ContextPart", instvarsize=constants.BLKCTX_STACK_START) # make better accessors for classes that can be found in special object # table for name in constants.classes_in_special_object_table.keys(): name = 'w_' + name - setattr(self, name, self.classtable.get(name)) + setattr(self, name, self.classtable[name]) - def make_bootstrap_objects(self): - def bld_char(i): - w_cinst = self.w_Character.as_class_get_shadow(self).new() + def bld_char(self, i): + w_cinst = self.classtable['w_Charactertable'].as_class_get_shadow(self).new() w_cinst.store(self, constants.CHARACTER_VALUE_INDEX, model.W_SmallInteger(i)) return w_cinst + + def make_bootstrap_objects(self): w_charactertable = model.W_PointersObject( self.classtable['w_Array'], 256) self.w_charactertable = w_charactertable for i in range(256): - self.w_charactertable.atput0(self, i, bld_char(i)) + self.w_charactertable.atput0(self, i, self.bld_char(i)) # Very special nil hack: in order to allow W_PointersObject's to @@ -146,14 +148,22 @@ self.w_zero = model.W_SmallInteger(0) self.w_one = model.W_SmallInteger(1) self.w_two = model.W_SmallInteger(2) - self.objtable = {} - - for name in constants.objects_in_special_object_table: - name = "w_" + name - try: - self.objtable[name] = locals()[name] - except KeyError, e: - self.objtable[name] = None + self.objtable = { + "w_nil" : w_nil, + "w_true" : w_true, + "w_false" : w_false, + "w_charactertable" : w_charactertable, + "w_schedulerassociationpointer" : None, + "w_smalltalkdict" : None, + } + + # XXX Does not work when we load images dynamically! + # for name in constants.objects_in_special_object_table: + # name = "w_" + name + # try: + # self.objtable[name] = locals()[name] + # except KeyError, e: + # self.objtable[name] = None # methods for wrapping and unwrapping stuff @@ -167,7 +177,7 @@ return model.W_Float(i) def wrap_string(self, string): - w_inst = self.w_String.as_class_get_shadow(self).new(len(string)) + w_inst = self.classtable['w_String'].as_class_get_shadow(self).new(len(string)) for i in range(len(string)): w_inst.setchar(i, string[i]) return w_inst @@ -187,7 +197,7 @@ a wrapped smalltalk array """ lstlen = len(lst_w) - res = self.w_Array.as_class_get_shadow().new(lstlen) + res = self.classtable['w_Array'].as_class_get_shadow().new(lstlen) for i in range(lstlen): res.storevarpointer(i, lit[i]) return res @@ -200,11 +210,11 @@ def unwrap_char(self, w_char): from pypy.lang.smalltalk import constants w_class = w_char.getclass(self) - if not w_class.is_same_object(self.w_Character): + if not w_class.is_same_object(self.classtable['w_Character']): raise UnwrappingError("expected character, got %s" % (w_class, )) w_ord = w_char.fetch(self, constants.CHARACTER_VALUE_INDEX) w_class = w_ord.getclass(self) - if not w_class.is_same_object(self.w_SmallInteger): + if not w_class.is_same_object(self.classtable['w_SmallInteger']): raise UnwrappingError("expected smallint from character, got %s" % (w_class, )) assert isinstance(w_ord, model.W_SmallInteger) @@ -217,7 +227,6 @@ raise UnwrappingError() - def bootstrap_class(space, instsize, w_superclass=None, w_metaclass=None, name='?', format=shadow.POINTERS, varsized=False): from pypy.lang.smalltalk import model Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/primitives.py (original) +++ pypy/trunk/pypy/lang/smalltalk/primitives.py Wed Feb 25 11:05:01 2009 @@ -503,8 +503,8 @@ # 1. Rcvr or arg are SmallIntegers # XXX this is wrong too - if (w_arg_class.is_same_object(interp.space.w_SmallInteger) or - w_rcvr_class.is_same_object(interp.space.w_SmallInteger)): + if (w_arg_class.is_same_object(interp.space.classtable['w_SmallInteger']) or + w_rcvr_class.is_same_object(interp.space.classtable['w_SmallInteger'])): raise PrimitiveFailedError() # 2. Rcvr is an instance of a compact class and argument isn't @@ -704,7 +704,7 @@ # XXX need to check this since VALUE is called on all sorts of objects. if not w_block_ctx.getclass(interp.space).is_same_object( - interp.space.w_BlockContext): + interp.space.classtable['w_BlockContext']): raise PrimitiveFailedError() assert isinstance(w_block_ctx, model.W_PointersObject) @@ -736,7 +736,7 @@ # Check that our arguments have pointers format and the right size: if not w_args.getclass(interp.space).is_same_object( - interp.space.w_Array): + interp.space.classtable['w_Array']): raise PrimitiveFailedError() if w_args.size() != exp_arg_cnt: raise PrimitiveFailedError() Modified: pypy/trunk/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/shadow.py (original) +++ pypy/trunk/pypy/lang/smalltalk/shadow.py Wed Feb 25 11:05:01 2009 @@ -323,7 +323,7 @@ def is_block_context(w_pointers, space): method_or_argc = w_pointers.fetch(space, constants.MTHDCTX_METHOD) return method_or_argc.getclass(space).is_same_object( - space.w_SmallInteger) + space.classtable['w_SmallInteger']) def fetch(self, n0): if n0 == constants.CTXPART_SENDER_INDEX: @@ -509,7 +509,7 @@ # into the right places in the W_PointersObject # XXX could hack some more to never have to create the _vars of w_result contextsize = w_home.as_methodcontext_get_shadow(space).myblocksize() - w_result = model.W_PointersObject(space.w_BlockContext, contextsize) + w_result = model.W_PointersObject(space.classtable['w_BlockContext'], contextsize) s_result = BlockContextShadow(space, w_result) w_result.store_shadow(s_result) s_result.store_expected_argument_count(argcnt) @@ -603,7 +603,7 @@ # From blue book: normal mc have place for 12 temps+maxstack # mc for methods with islarge flag turned on 32 size = 12 + w_method.islarge * 20 + w_method.argsize - w_result = space.w_MethodContext.as_class_get_shadow(space).new(size) + w_result = space.classtable['w_MethodContext'].as_class_get_shadow(space).new(size) assert isinstance(w_result, model.W_PointersObject) # create and attach a shadow manually, to not have to carefully put things # into the right places in the W_PointersObject From tverwaes at codespeak.net Wed Feb 25 11:12:38 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 25 Feb 2009 11:12:38 +0100 (CET) Subject: [pypy-svn] r62132 - pypy/trunk/pypy/lang/smalltalk Message-ID: <20090225101238.EDFF4168402@codespeak.net> Author: tverwaes Date: Wed Feb 25 11:12:38 2009 New Revision: 62132 Modified: pypy/trunk/pypy/lang/smalltalk/objspace.py Log: fixed a woops. of course we want to put characters in the table not tables in the table... Modified: pypy/trunk/pypy/lang/smalltalk/objspace.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/objspace.py (original) +++ pypy/trunk/pypy/lang/smalltalk/objspace.py Wed Feb 25 11:12:38 2009 @@ -121,7 +121,7 @@ setattr(self, name, self.classtable[name]) def bld_char(self, i): - w_cinst = self.classtable['w_Charactertable'].as_class_get_shadow(self).new() + w_cinst = self.classtable['w_Character'].as_class_get_shadow(self).new() w_cinst.store(self, constants.CHARACTER_VALUE_INDEX, model.W_SmallInteger(i)) return w_cinst From arigo at codespeak.net Wed Feb 25 13:09:41 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 13:09:41 +0100 (CET) Subject: [pypy-svn] r62135 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090225120941.0E74E16842F@codespeak.net> Author: arigo Date: Wed Feb 25 13:09:39 2009 New Revision: 62135 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_send.py pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: RPythonification. All tests pass, apart from test_zrpy_virtualizable. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Wed Feb 25 13:09:39 2009 @@ -141,7 +141,7 @@ else: return repr(x) -def repr_list(lst, types, cpu): +def repr_list(lst, types, memocast): res_l = [] if types and types[-1] == 'varargs': types = types[:-1] + ('int',) * (len(lst) - len(types) + 1) @@ -152,12 +152,12 @@ else: extraarg = None if isinstance(elem, Constant): - res_l.append('(%s)' % repr1(elem, tp, cpu, extraarg)) + res_l.append('(%s)' % repr1(elem, tp, memocast, extraarg)) else: - res_l.append(repr1(elem, tp, cpu, extraarg)) + res_l.append(repr1(elem, tp, memocast, extraarg)) return '[%s]' % (', '.join(res_l)) -def repr1(x, tp, cpu, extraarg): +def repr1(x, tp, memocast, extraarg): if tp == "intorptr": if extraarg % 2: tp = "ptr" @@ -172,7 +172,7 @@ return '(* None)' if isinstance(x, int): # XXX normalize? - ptr = str(cpu.cast_int_to_adr(x)) + ptr = str(cast_int_to_adr(memocast, x)) else: if getattr(x, '_fake', None): return repr(x) @@ -270,9 +270,9 @@ op.jump_target_index = loop_target_index if op.opname == 'jump': if loop_target == loop and loop_target_index == 0: - log.trace("compiling new loop") + log.info("compiling new loop") else: - log.trace("compiling new bridge") + log.info("compiling new bridge") def compile_add_failnum(loop, failnum): loop = _from_opaque(loop) @@ -296,16 +296,15 @@ class Frame(object): - def __init__(self, cpu): - assert cpu + def __init__(self, memocast): llinterp = LLInterpreter(_rtyper) # '_rtyper' set by CPU llinterp.traceback_frames = [] self.llframe = ExtendedLLFrame(None, None, llinterp) - self.llframe.cpu = cpu + self.llframe.memocast = memocast self.llframe.last_exception = None self.llframe.last_exception_handled = True - self.verbose = False # cpu is not None - self.cpu = cpu + self.verbose = False + self.memocast = memocast def getenv(self, v): if isinstance(v, Constant): @@ -402,10 +401,10 @@ extraarg = values[1] else: extraarg = None - resdata = '-> ' + repr1(res, restype, self.cpu, extraarg) + resdata = '-> ' + repr1(res, restype, self.memocast, extraarg) # fish the types log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes, - self.cpu), resdata)) + self.memocast), resdata)) if res is None: return [] elif isinstance(res, list): @@ -417,9 +416,9 @@ TP = lltype.typeOf(x) if isinstance(TP, lltype.Ptr): assert TP.TO._gckind == 'raw' - return self.cpu.cast_adr_to_int(llmemory.cast_ptr_to_adr(x)) + return cast_adr_to_int(self.memocast, llmemory.cast_ptr_to_adr(x)) if TP == llmemory.Address: - return self.cpu.cast_adr_to_int(x) + return cast_adr_to_int(self.memocast, x) return lltype.cast_primitive(lltype.Signed, x) def as_ptr(self, x): @@ -434,8 +433,8 @@ log.trace('ran %d operations, %d jumps' % (count, count_jumps)) -def new_frame(cpu): - frame = Frame(cpu) +def new_frame(memocast): + frame = Frame(memocast) return _to_opaque(frame) def frame_clear(frame, loop, opindex): @@ -581,13 +580,13 @@ def op_guard_nonnull(self, ptr): if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = self.cpu.cast_int_to_adr(ptr) + ptr = cast_int_to_adr(self.memocast, ptr) if not ptr: raise GuardFailed def op_guard_isnull(self, ptr): if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = self.cpu.cast_int_to_adr(ptr) + ptr = cast_int_to_adr(self.memocast, ptr) if ptr: raise GuardFailed @@ -621,7 +620,7 @@ def op_guard_class(self, value, expected_class): value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value) expected_class = llmemory.cast_adr_to_ptr( - self.cpu.cast_int_to_adr(expected_class), + cast_int_to_adr(self.memocast, expected_class), rclass.CLASSTYPE) if value.typeptr != expected_class: raise GuardFailed @@ -643,7 +642,7 @@ def op_guard_exception(self, expected_exception): expected_exception = llmemory.cast_adr_to_ptr( - self.cpu.cast_int_to_adr(expected_exception), + cast_int_to_adr(self.memocast, expected_exception), rclass.CLASSTYPE) assert expected_exception if self.last_exception: @@ -673,7 +672,7 @@ def op_getfield_raw(self, intval, fielddesc): STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] - ptr = llmemory.cast_adr_to_ptr(self.cpu.cast_int_to_adr(intval), + ptr = llmemory.cast_adr_to_ptr(cast_int_to_adr(self.memocast, intval), lltype.Ptr(STRUCT)) return getattr(ptr, fieldname) @@ -689,25 +688,25 @@ if isinstance(FIELDTYPE, lltype.Ptr): assert FIELDTYPE.TO._gckind == 'raw' newvalue = llmemory.cast_adr_to_ptr( - self.cpu.cast_int_to_adr(newvalue), + cast_int_to_adr(self.memocast, newvalue), FIELDTYPE) elif FIELDTYPE == llmemory.Address: - newvalue = self.cpu.cast_int_to_adr(newvalue) + newvalue = cast_int_to_adr(self.memocast, newvalue) setattr(ptr, fieldname, newvalue) def op_setfield_raw(self, intval, fielddesc, newvalue): - ptr = llmemory.cast_adr_to_ptr(self.cpu.cast_int_to_adr(intval), + ptr = llmemory.cast_adr_to_ptr(cast_int_to_adr(self.memocast, intval), lltype.Ptr(STRUCT)) self.op_setfield_gc(ptr, fielddesc, newvalue) def op_ooisnull(self, ptr): if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = self.cpu.cast_int_to_adr(ptr) + ptr = cast_int_to_adr(self.memocast, ptr) return not ptr def op_oononnull(self, ptr): if lltype.typeOf(ptr) != llmemory.GCREF: - ptr = self.cpu.cast_int_to_adr(ptr) + ptr = cast_int_to_adr(self.memocast, ptr) return bool(ptr) def op_oois(self, ptr1, ptr2): @@ -745,7 +744,7 @@ self.last_exception = None def do_call(self, f, *args): - ptr = self.cpu.cast_int_to_adr(f).ptr + ptr = cast_int_to_adr(self.memocast, f).ptr FUNC = lltype.typeOf(ptr).TO ARGS = FUNC.ARGS args = list(args) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Wed Feb 25 13:09:39 2009 @@ -22,7 +22,7 @@ self.stats = stats or MiniStats() self.stats.exec_counters = {} self.stats.exec_jumps = 0 - self.memo_cast = lltype.nullptr(llimpl.MEMOCAST.TO) + self.memo_cast = llimpl.new_memo_cast() llimpl._stats = self.stats llimpl._rtyper = self.rtyper if translate_support_code: @@ -103,7 +103,7 @@ follow the merge point. """ assert result_type is None or isinstance(result_type, str) - frame = llimpl.new_frame(self) + frame = llimpl.new_frame(self.memo_cast) llimpl.frame_clear(frame, merge_point._compiled, merge_point._opindex) for box in valueboxes: if isinstance(box, history.BoxInt): @@ -122,7 +122,7 @@ if opname[0] == '#': return None c = self.get_compiled_single_op(opname, valueboxes, result_type) - frame = llimpl.new_frame(self) + frame = llimpl.new_frame(self.memo_cast) llimpl.frame_clear(frame, c, 0) for box in valueboxes: if box.type == 'int': @@ -269,8 +269,6 @@ return ofs_length def cast_adr_to_int(self, adr): - if not self.memo_cast: - self.memo_cast = llimpl.new_memo_cast() return llimpl.cast_adr_to_int(self.memo_cast, adr) def cast_int_to_adr(self, int): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Wed Feb 25 13:09:39 2009 @@ -69,6 +69,7 @@ __slots__ = () def _new(x, cpu): + "NOT_RPYTHON" T = lltype.typeOf(x) kind = getkind(T) if kind == "int": @@ -199,6 +200,7 @@ @staticmethod def _new(x, cpu): + "NOT_RPYTHON" kind = getkind(lltype.typeOf(x)) if kind == "int": intval = lltype.cast_primitive(lltype.Signed, x) @@ -438,7 +440,7 @@ if not canfold: self.record(step, argboxes, resboxes) return resboxes - execute_and_record._annspecialcase_ = 'specialize:arg(3, 4)' + execute_and_record._annspecialcase_ = 'specialize:arg(4)' def record(self, opname, argboxes, resboxes, opcls=ResOperation): # xxx the indirection from record to _record is to work Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Wed Feb 25 13:09:39 2009 @@ -1,6 +1,7 @@ import py from pypy.rpython.lltypesystem import lltype, llmemory, rclass from pypy.rpython.llinterp import LLException +from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import we_are_translated, r_dict from pypy.rlib.unroll import unrolling_iterable @@ -629,7 +630,7 @@ if len(resboxes) == 1: resultbox = resboxes[0] self.make_result_box(resultbox) - execute._annspecialcase_ = 'specialize:arg(3, 4)' + execute._annspecialcase_ = 'specialize:arg(4)' def execute_with_exc(self, step, argboxes, result_type, pure=False): old_index = len(self.metainterp.history.operations) @@ -641,7 +642,8 @@ raise etype, evalue = e.args[:2] else: - XXX + evalue = cast_instance_to_base_ptr(e) + etype = evalue.typeptr if result_type == 'void': resultboxes = [] else: @@ -662,7 +664,7 @@ llmemory.cast_ptr_to_adr(etype)) value_as_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, evalue) return self.metainterp.handle_exception(type_as_int, value_as_gcref) - execute_with_exc._annspecialcase_ = 'specialize:arg(3, 4)' + execute_with_exc._annspecialcase_ = 'specialize:arg(4)' # ____________________________________________________________ @@ -759,8 +761,8 @@ else: debug_print('LEAVE') - def compile_and_run(self, args): - orig_boxes = self.initialize_state_from_start(args) + def compile_and_run(self, *args): + orig_boxes = self.initialize_state_from_start(*args) try: self.interpret() assert False, "should always raise" @@ -843,17 +845,30 @@ specnode.extract_runtime_data(self.cpu, args[i], expanded_args) return expanded_args - def initialize_state_from_start(self, args): + def _initialize_from_start(self, original_boxes, num_green_args, *args): + if args: + value = args[0] + if isinstance(lltype.typeOf(value), lltype.Ptr): + value = lltype.cast_opaque_ptr(llmemory.GCREF, value) + if num_green_args > 0: + cls = ConstPtr + else: + cls = BoxPtr + else: + if num_green_args > 0: + cls = ConstInt + else: + cls = BoxInt + box = cls(value) + original_boxes.append(box) + self._initialize_from_start(original_boxes, num_green_args-1, + *args[1:]) + + def initialize_state_from_start(self, *args): self.create_empty_history() num_green_args = self.num_green_args original_boxes = [] - for i in range(len(args)): - value = args[i] - if i < num_green_args: - box = Const._new(value, self.cpu) - else: - box = Box._new(value, self.cpu) - original_boxes.append(box) + self._initialize_from_start(original_boxes, num_green_args, *args) # ----- make a new frame ----- self.framestack = [] f = self.newframe(self.portal_code) @@ -867,7 +882,6 @@ self.history = history.History(self.cpu) else: self.history = history.BlackHole(self.cpu) - self.guard_failure = guard_failure guard_op = guard_failure.guard_op boxes_from_frame = [] index = 0 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/specnode.py Wed Feb 25 13:09:39 2009 @@ -10,7 +10,16 @@ resultlist.append(valuebox) def adapt_to(self, instnode): - instnode.escaped = True + instnode.escaped = True + + def mutate_nodes(self, instnode): + raise NotImplementedError + + def equals(self, other): + raise NotImplementedError + + def matches(self, other): + raise NotImplementedError class NotSpecNode(SpecNode): def mutate_nodes(self, instnode): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Wed Feb 25 13:09:39 2009 @@ -161,8 +161,9 @@ w.foo() y -= 1 return 42 + policy = StopAtXPolicy(externfn) for j in range(69, 75): - res = self.meta_interp(f, [j], policy=StopAtXPolicy(externfn)) + res = self.meta_interp(f, [j], policy=policy) assert res == 42 self.check_loop_count(3) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_basic.py Wed Feb 25 13:09:39 2009 @@ -21,9 +21,12 @@ assert res == 490 def test_loop_2(self): + jitdriver = JitDriver(greens = [], reds = ['i', 'total']) def f(i): total = 0 while i > 3: + jitdriver.can_enter_jit(i=i, total=total) + jitdriver.jit_merge_point(i=i, total=total) total += i if i >= 10: i -= 2 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_zrpy_send.py Wed Feb 25 13:09:39 2009 @@ -4,8 +4,4 @@ class TestLLSend(test_send.SendTests, LLInterpJitMixin): - def test_oosend_guard_failure(self): - py.test.skip("Fails with assertion error") - - def test_oosend_guard_failure_2(self): - py.test.skip("Fails with assertion error") + pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py Wed Feb 25 13:09:39 2009 @@ -1,7 +1,9 @@ from pypy.jit.metainterp import history from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.annlowlevel import llhelper +from pypy.rpython.annlowlevel import llhelper, cast_base_ptr_to_instance +from pypy.annotation.model import lltype_to_annotation +from pypy.rlib.objectmodel import we_are_translated class VirtualizableDesc(history.AbstractValue): hash = 0 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Wed Feb 25 13:09:39 2009 @@ -27,12 +27,13 @@ warmrunnerdesc = WarmRunnerDesc(translator, **kwds) warmrunnerdesc.state.set_param_threshold(3) # for tests warmrunnerdesc.state.set_param_trace_eagerness(2) # for tests + warmrunnerdesc.finish() return interp.eval_graph(graph, args) -def rpython_ll_meta_interp(function, args, loops='not used right now', **kwds): - return ll_meta_interp(function, args, - translate_support_code=True, backendopt=True, - **kwds) +def rpython_ll_meta_interp(function, args, backendopt=True, + loops='not used right now', **kwds): + return ll_meta_interp(function, args, backendopt=backendopt, + translate_support_code=True, **kwds) def find_can_enter_jit(graphs): results = [] @@ -86,6 +87,8 @@ self.rewrite_jit_merge_point() self.metainterp.num_green_args = self.num_green_args self.metainterp.state = self.state + + def finish(self): if self.cpu.translate_support_code: self.annhelper.finish() @@ -461,7 +464,7 @@ getkeyhash._always_inline_ = True def compile_and_run(self, argshash, *args): - loop, boxes = warmrunnerdesc.metainterp.compile_and_run(list(args)) + loop, boxes = warmrunnerdesc.metainterp.compile_and_run(*args) if loop: cpu = warmrunnerdesc.metainterp.cpu mp = loop.operations[0] From arigo at codespeak.net Wed Feb 25 13:14:33 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 13:14:33 +0100 (CET) Subject: [pypy-svn] r62136 - in pypy/branch/pyjitpl5/pypy/jit: metainterp-bak old-metainterp Message-ID: <20090225121433.A718616842F@codespeak.net> Author: arigo Date: Wed Feb 25 13:14:33 2009 New Revision: 62136 Added: pypy/branch/pyjitpl5/pypy/jit/old-metainterp/ - copied from r62135, pypy/branch/pyjitpl5/pypy/jit/metainterp-bak/ Removed: pypy/branch/pyjitpl5/pypy/jit/metainterp-bak/ Log: Rename this directory to ease completion. From arigo at codespeak.net Wed Feb 25 13:44:06 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 13:44:06 +0100 (CET) Subject: [pypy-svn] r62137 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090225124406.9CEA516844C@codespeak.net> Author: arigo Date: Wed Feb 25 13:44:06 2009 New Revision: 62137 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: Oups. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Wed Feb 25 13:44:06 2009 @@ -63,7 +63,7 @@ metainterp.DoneWithThisFrame = DoneWithThisFrame self.metainterp = metainterp try: - metainterp.compile_and_run(args) + metainterp.compile_and_run(*args) except DoneWithThisFrame, e: return e.args[0].value else: From arigo at codespeak.net Wed Feb 25 14:25:22 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 14:25:22 +0100 (CET) Subject: [pypy-svn] r62138 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090225132522.92F9A168409@codespeak.net> Author: arigo Date: Wed Feb 25 14:25:20 2009 New Revision: 62138 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: Test and fix for cases where the policy decides that, in an indirect_call, some of the called graphs must be seen but others not. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Wed Feb 25 14:25:20 2009 @@ -210,9 +210,11 @@ def __init__(self, codewriter, graph, portal): self.codewriter = codewriter self.cpu = codewriter.metainterp.cpu - self.graph = graph self.portal = portal - self.bytecode = self.codewriter.get_jitcode(self.graph) + self.bytecode = self.codewriter.get_jitcode(graph) + if not codewriter.policy.look_inside_graph(graph): + graph = make_calling_stub(codewriter.rtyper, graph) + self.graph = graph def assemble(self): """Assemble the opcodes for self.bytecode.""" @@ -620,11 +622,11 @@ # return getattr(self, 'handle_%s_call' % color)(op) def serialize_op_direct_call(self, op): - self.minimize_variables() color = self.codewriter.policy.guess_call_kind(op) return getattr(self, 'handle_%s_call' % color)(op) def handle_regular_call(self, op): + self.minimize_variables() [targetgraph] = self.codewriter.policy.graphs_from(op) jitbox = self.codewriter.get_jitcode(targetgraph) self.emit('call') @@ -633,15 +635,8 @@ if x.concretetype is not lltype.Void]) self.register_var(op.result) -# def handle_green_call(self, op): -# assert op.result.concretetype is not lltype.Void -# self.emit('green_call_%s' % getkind_num(self.cpu, -# op.result.concretetype)) -# self.emit_varargs([x for x in op.args -# if x.concretetype is not lltype.Void]) -# self.register_var(op.result) - def handle_residual_call(self, op): + self.minimize_variables() self.emit('residual_call_%s' % getkind_num(self.cpu, op.result.concretetype)) self.emit_varargs([x for x in op.args @@ -689,28 +684,6 @@ self.emit_varargs([c_func] + args) self.register_var(op.result) -# def serialize_op_indirect_call(self, op): -# xxx -# color = support.guess_call_kind(self.codewriter.hannotator, op) -# return getattr(self, 'handle_%s_indirect_call' % color)(op) - -# def handle_red_indirect_call(self, op): -# # indirect_call to a red function pointer -# # XXX for now, this is handled as a residual call -# self.handle_residual_indirect_call(op) - -# def handle_direct_indirect_call(self, op): -# # indirect_call to a green function pointer -# self.minimize_variables() -# targets = support.graphs_from(self.codewriter.hannotator, op) -# indirectcallset = self.codewriter.get_indirectcallset(targets) -# self.emit('direct_indirect_call') -# self.emit(self.get_position(indirectcallset)) -# self.emit(self.var_position(op.args[0])) -# self.emit_varargs([x for x in op.args[1:-1] -# if x.concretetype is not lltype.Void]) -# self.register_var(op.result) - def serialize_op_indirect_call(self, op): self.minimize_variables() targets = self.codewriter.policy.graphs_from(op) @@ -840,3 +813,23 @@ result[i + 1] = chr((index >> 8) & 0xff) result[i + 2] = chr(index & 0xff) return "".join(result) + +# ____________________________________________________________ + +def make_calling_stub(rtyper, graph): + from pypy.objspace.flow.model import Block, Link, FunctionGraph + from pypy.objspace.flow.model import SpaceOperation + from pypy.translator.unsimplify import copyvar + # + args_v = [copyvar(None, v) for v in graph.getargs()] + v_res = copyvar(None, graph.getreturnvar()) + fnptr = rtyper.getcallable(graph) + v_ptr = Constant(fnptr, lltype.typeOf(fnptr)) + newstartblock = Block(args_v) + newstartblock.operations.append( + SpaceOperation('direct_call', [v_ptr] + args_v, v_res)) + newgraph = FunctionGraph('%s_ts_stub' % (graph.name,), newstartblock) + newgraph.getreturnvar().concretetype = v_res.concretetype + newstartblock.closeblock(Link([v_res], newgraph.returnblock)) + newgraph.ts_stub_for = graph + return newgraph Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py Wed Feb 25 14:25:20 2009 @@ -1,14 +1,32 @@ -class JitPolicy: +class JitPolicy(object): + + def look_inside_function(self, func): + # explicitly pure functions are always opaque + if getattr(func, '_pure_function_', False): + return False + return True + + def look_inside_graph(self, graph): + try: + func = graph.func + except AttributeError: + return True + return self.look_inside_function(func) + def graphs_from(self, op): if op.opname == 'direct_call': graph = op.args[0].value._obj.graph - # explicitly pure functions are always opaque - if getattr(getattr(graph, 'func', None), '_pure_function_', False): - return None - return [graph] - assert op.opname == 'indirect_call' - return op.args[-1].value + if self.look_inside_graph(graph): + return [graph] # common case: look inside this graph + else: + assert op.opname == 'indirect_call' + graphs = op.args[-1].value + for graph in graphs: + if self.look_inside_graph(graph): + return graphs # common case: look inside at least 1 graph + # residual call case: we don't need to look into any graph + return None def guess_call_kind(self, op): targetgraphs = self.graphs_from(op) @@ -26,11 +44,7 @@ def __init__(self, *funcs): self.funcs = funcs - def graphs_from(self, op): - graphs = JitPolicy.graphs_from(self, op) - if graphs is None or len(graphs) > 1: # XXX a hack - return graphs - [graph] = graphs - if getattr(graph, 'func', None) in self.funcs: - return None - return [graph] + def look_inside_function(self, func): + if func in self.funcs: + return False + return super(StopAtXPolicy, self).look_inside_function(func) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Wed Feb 25 14:25:20 2009 @@ -179,6 +179,28 @@ res = self.meta_interp(f, [31]) assert res == -4 + def test_stopatxpolicy(self): + myjitdriver = JitDriver(greens = [], reds = ['y']) + def internfn(y): + return y * 3 + def externfn(y): + return y % 4 + def f(y): + while y >= 0: + myjitdriver.can_enter_jit(y=y) + myjitdriver.jit_merge_point(y=y) + if y & 7: + f = internfn + else: + f = externfn + f(y) + y -= 1 + return 42 + policy = StopAtXPolicy(externfn) + res = self.meta_interp(f, [31], policy=policy) + assert res == 42 + self.check_loops(int_mul=1, int_mod=0) + class TestOOtype(BasicTests, OOJitMixin): pass From cfbolz at codespeak.net Wed Feb 25 14:40:31 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Feb 2009 14:40:31 +0100 (CET) Subject: [pypy-svn] r62139 - in pypy/trunk/pypy: config objspace/std objspace/std/test Message-ID: <20090225134031.C3B4D16849C@codespeak.net> Author: cfbolz Date: Wed Feb 25 14:40:31 2009 New Revision: 62139 Modified: pypy/trunk/pypy/config/pypyoption.py pypy/trunk/pypy/objspace/std/test/test_typeobject.py pypy/trunk/pypy/objspace/std/typeobject.py Log: Make it possible with a translation-time option to make Python builtin-types mutable. Modified: pypy/trunk/pypy/config/pypyoption.py ============================================================================== --- pypy/trunk/pypy/config/pypyoption.py (original) +++ pypy/trunk/pypy/config/pypyoption.py Wed Feb 25 14:40:31 2009 @@ -323,6 +323,8 @@ ChoiceOption("multimethods", "the multimethod implementation to use", ["doubledispatch", "mrd"], default="mrd"), + BoolOption("immutable_builtintypes", + "Forbid the changing of builtin types", default=True), ]), ]) Modified: pypy/trunk/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_typeobject.py Wed Feb 25 14:40:31 2009 @@ -1,5 +1,6 @@ from pypy.objspace.std.objspace import * from pypy.objspace.std.stdtypedef import * +from pypy.conftest import gettestobjspace ##class TestSpecialMultimethodCode(testit.TestCase): @@ -924,3 +925,22 @@ return 0 raises(TypeError, X) + +class AppTestMutableBuiltintypes: + + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.immutable_builtintypes": False}) + + def test_mutate_builtintype(self): + list.a = 1 + def doublelen(self): + return len(self) * 2 + list.doublelen = doublelen + l = [] + assert l.a == 1 + l.append(100) + assert l.doublelen() == 2 + del list.doublelen + del list.a + raises(AttributeError, "l.a") + Modified: pypy/trunk/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/typeobject.py (original) +++ pypy/trunk/pypy/objspace/std/typeobject.py Wed Feb 25 14:40:31 2009 @@ -629,7 +629,8 @@ space.set(w_descr, w_type, w_value) return - if not w_type.is_heaptype(): + if (space.config.objspace.std.immutable_builtintypes + and not w_type.is_heaptype()): msg = "can't set attributes on type object '%s'" %(w_type.name,) raise OperationError(space.w_TypeError, space.wrap(msg)) if name == "__del__" and name not in w_type.dict_w: @@ -647,8 +648,8 @@ if space.is_data_descr(w_descr): space.delete(w_descr, w_type) return - if not w_type.is_heaptype(): - msg = "can't delete attributes on type object '%s'" %(w_type.name,) + if (space.config.objspace.std.immutable_builtintypes + and not w_type.is_heaptype()): raise OperationError(space.w_TypeError, space.wrap(msg)) try: del w_type.dict_w[name] From cfbolz at codespeak.net Wed Feb 25 14:45:02 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Feb 2009 14:45:02 +0100 (CET) Subject: [pypy-svn] r62140 - in pypy/trunk/pypy: lang/smalltalk translator/goal Message-ID: <20090225134502.31066168423@codespeak.net> Author: cfbolz Date: Wed Feb 25 14:45:01 2009 New Revision: 62140 Modified: pypy/trunk/pypy/lang/smalltalk/constants.py pypy/trunk/pypy/lang/smalltalk/model.py pypy/trunk/pypy/lang/smalltalk/objspace.py pypy/trunk/pypy/lang/smalltalk/primitives.py pypy/trunk/pypy/lang/smalltalk/shadow.py pypy/trunk/pypy/translator/goal/targetimageloadingsmalltalk.py Log: Partially revert revision r62131. The object space is supposed to be created at translation time, not at runtime. This fixes translation. Modified: pypy/trunk/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/constants.py (original) +++ pypy/trunk/pypy/lang/smalltalk/constants.py Wed Feb 25 14:45:01 2009 @@ -131,8 +131,5 @@ "smalltalkdict" : SO_SMALLTALK, } -BITS = 32 -# Above should become: -# BITS = LONG_BIT -TAGGED_MAXINT = 2 ** (BITS - 2) - 1 -TAGGED_MININT = -2 ** (BITS - 2) +TAGGED_MAXINT = 2 ** (LONG_BIT - 2) - 1 +TAGGED_MININT = -2 ** (LONG_BIT - 2) Modified: pypy/trunk/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/model.py (original) +++ pypy/trunk/pypy/lang/smalltalk/model.py Wed Feb 25 14:45:01 2009 @@ -106,7 +106,7 @@ def getclass(self, space): """Return SmallInteger from special objects array.""" - return space.classtable['w_SmallInteger'] + return space.w_SmallInteger def gethash(self): return self.value @@ -142,7 +142,7 @@ def getclass(self, space): """Return Float from special objects array.""" - return space.classtable['w_Float'] + return space.w_Float def gethash(self): return 41 # XXX check this @@ -202,8 +202,7 @@ Float).""" def __init__(self, w_class): - if w_class is not None: # it's None for testing and bootstrapping the - # class hierarchy + if w_class is not None: # it's None only for testing assert isinstance(w_class, W_PointersObject) self.w_class = w_class @@ -219,9 +218,7 @@ return self._shadow.getname() else: name = None - if (hasattr(self, 'w_class') and - self.w_class is not None and - self.w_class._shadow is not None): + if self.w_class._shadow is not None: name = self.w_class._shadow.name return "a %s" % (name or '?',) @@ -413,10 +410,10 @@ # TODO: Completely untested! This failed translation bigtime... # XXX Probably we want to allow all subclasses if not (w_value.getclass(space).is_same_object( - space.classtable['w_LargePositiveInteger']) and - w_value.size() == 4): + space.w_LargePositiveInteger) and + w_value.size() == 4): raise error.UnwrappingError("Failed to convert bytes to word") - word = 0 + word = 0 for i in range(4): word += ord(w_value.getchar(i)) << 8*i else: @@ -477,7 +474,7 @@ return self.w_compiledin def getclass(self, space): - return space.classtable['w_CompiledMethod'] + return space.w_CompiledMethod def getliteral(self, index): # We changed this part Modified: pypy/trunk/pypy/lang/smalltalk/objspace.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/objspace.py (original) +++ pypy/trunk/pypy/lang/smalltalk/objspace.py Wed Feb 25 14:45:01 2009 @@ -10,36 +10,16 @@ self.make_bootstrap_classes() self.make_bootstrap_objects() - def define_core_cls(self, name, w_superclass, w_metaclass): - assert name.startswith('w_') - w_class = bootstrap_class(self, instsize=0, # XXX - w_superclass=w_superclass, - w_metaclass=w_metaclass, - name=name[2:]) - self.classtable[name] = w_class - return w_class - - def define_cls(self, cls_nm, supercls_nm, instvarsize=0, - format=shadow.POINTERS, varsized=False): - assert cls_nm.startswith("w_") - meta_nm = cls_nm + "Class" - meta_super_nm = supercls_nm + "Class" - w_Metaclass = self.classtable["w_Metaclass"] - w_meta_cls = self.classtable[meta_nm] = \ - bootstrap_class(self, 0, # XXX - self.classtable[meta_super_nm], - w_Metaclass, - name=meta_nm[2:]) - w_cls = self.classtable[cls_nm] = \ - bootstrap_class(self, instvarsize, - self.classtable[supercls_nm], - w_meta_cls, - format=format, - varsized=varsized, - name=cls_nm[2:]) - - def make_bootstrap_classes(self): + def define_core_cls(name, w_superclass, w_metaclass): + assert name.startswith('w_') + w_class = bootstrap_class(self, instsize=0, # XXX + w_superclass=w_superclass, + w_metaclass=w_metaclass, + name=name[2:]) + self.classtable[name] = w_class + return w_class + # A complete minimal setup (including Behavior) would look like this # # class: superclass: metaclass: @@ -63,14 +43,14 @@ ["w_Class", "w_ClassDescription"], ["w_Metaclass", "w_ClassDescription"], ] - w_ProtoObjectClass = self.define_core_cls("w_ProtoObjectClass", None, None) - # w_ProtoObjectClass = self.classtable["w_ProtoObjectClass"] - self.define_core_cls("w_ProtoObject", None, w_ProtoObjectClass) + define_core_cls("w_ProtoObjectClass", None, None) + w_ProtoObjectClass = self.classtable["w_ProtoObjectClass"] + define_core_cls("w_ProtoObject", None, w_ProtoObjectClass) for (cls_nm, super_cls_nm) in cls_nm_tbl: meta_nm = cls_nm + "Class" meta_super_nm = super_cls_nm + "Class" - w_metacls = self.define_core_cls(meta_nm, self.classtable[meta_super_nm], None) - self.define_core_cls(cls_nm, self.classtable[super_cls_nm], w_metacls) + w_metacls = define_core_cls(meta_nm, self.classtable[meta_super_nm], None) + define_core_cls(cls_nm, self.classtable[super_cls_nm], w_metacls) w_Class = self.classtable["w_Class"] w_Metaclass = self.classtable["w_Metaclass"] # XXX @@ -85,53 +65,71 @@ if w_cls_obj.w_class is None: w_cls_obj.w_class = w_Metaclass - self.define_cls("w_Magnitude", "w_Object") - self.define_cls("w_Character", "w_Magnitude", instvarsize=1) - self.define_cls("w_Number", "w_Magnitude") - self.define_cls("w_Integer", "w_Number") - self.define_cls("w_SmallInteger", "w_Integer") - self.define_cls("w_LargePositiveInteger", "w_Integer", format=shadow.BYTES) - self.define_cls("w_Float", "w_Number", format=shadow.BYTES) - self.define_cls("w_Collection", "w_Object") - self.define_cls("w_SequenceableCollection", "w_Collection") - self.define_cls("w_ArrayedCollection", "w_SequenceableCollection") - self.define_cls("w_Array", "w_ArrayedCollection", varsized=True) - self.define_cls("w_String", "w_ArrayedCollection", format=shadow.BYTES) - self.define_cls("w_UndefinedObject", "w_Object") - self.define_cls("w_Boolean", "w_Object") - self.define_cls("w_True", "w_Boolean") - self.define_cls("w_False", "w_Boolean") - self.define_cls("w_ByteArray", "w_ArrayedCollection", format=shadow.BYTES) - self.define_cls("w_MethodDict", "w_Object", instvarsize=2, varsized=True) - self.define_cls("w_CompiledMethod", "w_ByteArray", format=shadow.COMPILED_METHOD) - self.define_cls("w_ContextPart", "w_Object") - self.define_cls("w_MethodContext", "w_ContextPart") - self.define_cls("w_Link", "w_Object") - self.define_cls("w_Process", "w_Link") - self.define_cls("w_Point", "w_Object") - self.define_cls("w_LinkedList", "w_SequenceableCollection") - self.define_cls("w_Semaphore", "w_LinkedList") - self.define_cls("w_BlockContext", "w_ContextPart", + def define_cls(cls_nm, supercls_nm, instvarsize=0, format=shadow.POINTERS, + varsized=False): + assert cls_nm.startswith("w_") + meta_nm = cls_nm + "Class" + meta_super_nm = supercls_nm + "Class" + w_Metaclass = self.classtable["w_Metaclass"] + w_meta_cls = self.classtable[meta_nm] = \ + bootstrap_class(self, 0, # XXX + self.classtable[meta_super_nm], + w_Metaclass, + name=meta_nm[2:]) + w_cls = self.classtable[cls_nm] = \ + bootstrap_class(self, instvarsize, + self.classtable[supercls_nm], + w_meta_cls, + format=format, + varsized=varsized, + name=cls_nm[2:]) + + define_cls("w_Magnitude", "w_Object") + define_cls("w_Character", "w_Magnitude", instvarsize=1) + define_cls("w_Number", "w_Magnitude") + define_cls("w_Integer", "w_Number") + define_cls("w_SmallInteger", "w_Integer") + define_cls("w_LargePositiveInteger", "w_Integer", format=shadow.BYTES) + define_cls("w_Float", "w_Number", format=shadow.BYTES) + define_cls("w_Collection", "w_Object") + define_cls("w_SequenceableCollection", "w_Collection") + define_cls("w_ArrayedCollection", "w_SequenceableCollection") + define_cls("w_Array", "w_ArrayedCollection", varsized=True) + define_cls("w_String", "w_ArrayedCollection", format=shadow.BYTES) + define_cls("w_UndefinedObject", "w_Object") + define_cls("w_Boolean", "w_Object") + define_cls("w_True", "w_Boolean") + define_cls("w_False", "w_Boolean") + define_cls("w_ByteArray", "w_ArrayedCollection", format=shadow.BYTES) + define_cls("w_MethodDict", "w_Object", instvarsize=2, varsized=True) + define_cls("w_CompiledMethod", "w_ByteArray", format=shadow.COMPILED_METHOD) + define_cls("w_ContextPart", "w_Object") + define_cls("w_MethodContext", "w_ContextPart") + define_cls("w_Link", "w_Object") + define_cls("w_Process", "w_Link") + define_cls("w_Point", "w_Object") + define_cls("w_LinkedList", "w_SequenceableCollection") + define_cls("w_Semaphore", "w_LinkedList") + define_cls("w_BlockContext", "w_ContextPart", instvarsize=constants.BLKCTX_STACK_START) # make better accessors for classes that can be found in special object # table for name in constants.classes_in_special_object_table.keys(): name = 'w_' + name - setattr(self, name, self.classtable[name]) + setattr(self, name, self.classtable.get(name)) - def bld_char(self, i): - w_cinst = self.classtable['w_Character'].as_class_get_shadow(self).new() + def make_bootstrap_objects(self): + def bld_char(i): + w_cinst = self.w_Character.as_class_get_shadow(self).new() w_cinst.store(self, constants.CHARACTER_VALUE_INDEX, model.W_SmallInteger(i)) return w_cinst - - def make_bootstrap_objects(self): w_charactertable = model.W_PointersObject( self.classtable['w_Array'], 256) self.w_charactertable = w_charactertable for i in range(256): - self.w_charactertable.atput0(self, i, self.bld_char(i)) + self.w_charactertable.atput0(self, i, bld_char(i)) # Very special nil hack: in order to allow W_PointersObject's to @@ -148,22 +146,14 @@ self.w_zero = model.W_SmallInteger(0) self.w_one = model.W_SmallInteger(1) self.w_two = model.W_SmallInteger(2) - self.objtable = { - "w_nil" : w_nil, - "w_true" : w_true, - "w_false" : w_false, - "w_charactertable" : w_charactertable, - "w_schedulerassociationpointer" : None, - "w_smalltalkdict" : None, - } - - # XXX Does not work when we load images dynamically! - # for name in constants.objects_in_special_object_table: - # name = "w_" + name - # try: - # self.objtable[name] = locals()[name] - # except KeyError, e: - # self.objtable[name] = None + self.objtable = {} + + for name in constants.objects_in_special_object_table: + name = "w_" + name + try: + self.objtable[name] = locals()[name] + except KeyError, e: + self.objtable[name] = None # methods for wrapping and unwrapping stuff @@ -177,7 +167,7 @@ return model.W_Float(i) def wrap_string(self, string): - w_inst = self.classtable['w_String'].as_class_get_shadow(self).new(len(string)) + w_inst = self.w_String.as_class_get_shadow(self).new(len(string)) for i in range(len(string)): w_inst.setchar(i, string[i]) return w_inst @@ -197,7 +187,7 @@ a wrapped smalltalk array """ lstlen = len(lst_w) - res = self.classtable['w_Array'].as_class_get_shadow().new(lstlen) + res = self.w_Array.as_class_get_shadow().new(lstlen) for i in range(lstlen): res.storevarpointer(i, lit[i]) return res @@ -210,11 +200,11 @@ def unwrap_char(self, w_char): from pypy.lang.smalltalk import constants w_class = w_char.getclass(self) - if not w_class.is_same_object(self.classtable['w_Character']): + if not w_class.is_same_object(self.w_Character): raise UnwrappingError("expected character, got %s" % (w_class, )) w_ord = w_char.fetch(self, constants.CHARACTER_VALUE_INDEX) w_class = w_ord.getclass(self) - if not w_class.is_same_object(self.classtable['w_SmallInteger']): + if not w_class.is_same_object(self.w_SmallInteger): raise UnwrappingError("expected smallint from character, got %s" % (w_class, )) assert isinstance(w_ord, model.W_SmallInteger) @@ -227,6 +217,7 @@ raise UnwrappingError() + def bootstrap_class(space, instsize, w_superclass=None, w_metaclass=None, name='?', format=shadow.POINTERS, varsized=False): from pypy.lang.smalltalk import model Modified: pypy/trunk/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/primitives.py (original) +++ pypy/trunk/pypy/lang/smalltalk/primitives.py Wed Feb 25 14:45:01 2009 @@ -503,8 +503,8 @@ # 1. Rcvr or arg are SmallIntegers # XXX this is wrong too - if (w_arg_class.is_same_object(interp.space.classtable['w_SmallInteger']) or - w_rcvr_class.is_same_object(interp.space.classtable['w_SmallInteger'])): + if (w_arg_class.is_same_object(interp.space.w_SmallInteger) or + w_rcvr_class.is_same_object(interp.space.w_SmallInteger)): raise PrimitiveFailedError() # 2. Rcvr is an instance of a compact class and argument isn't @@ -704,7 +704,7 @@ # XXX need to check this since VALUE is called on all sorts of objects. if not w_block_ctx.getclass(interp.space).is_same_object( - interp.space.classtable['w_BlockContext']): + interp.space.w_BlockContext): raise PrimitiveFailedError() assert isinstance(w_block_ctx, model.W_PointersObject) @@ -736,7 +736,7 @@ # Check that our arguments have pointers format and the right size: if not w_args.getclass(interp.space).is_same_object( - interp.space.classtable['w_Array']): + interp.space.w_Array): raise PrimitiveFailedError() if w_args.size() != exp_arg_cnt: raise PrimitiveFailedError() Modified: pypy/trunk/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/trunk/pypy/lang/smalltalk/shadow.py (original) +++ pypy/trunk/pypy/lang/smalltalk/shadow.py Wed Feb 25 14:45:01 2009 @@ -323,7 +323,7 @@ def is_block_context(w_pointers, space): method_or_argc = w_pointers.fetch(space, constants.MTHDCTX_METHOD) return method_or_argc.getclass(space).is_same_object( - space.classtable['w_SmallInteger']) + space.w_SmallInteger) def fetch(self, n0): if n0 == constants.CTXPART_SENDER_INDEX: @@ -509,7 +509,7 @@ # into the right places in the W_PointersObject # XXX could hack some more to never have to create the _vars of w_result contextsize = w_home.as_methodcontext_get_shadow(space).myblocksize() - w_result = model.W_PointersObject(space.classtable['w_BlockContext'], contextsize) + w_result = model.W_PointersObject(space.w_BlockContext, contextsize) s_result = BlockContextShadow(space, w_result) w_result.store_shadow(s_result) s_result.store_expected_argument_count(argcnt) @@ -603,7 +603,7 @@ # From blue book: normal mc have place for 12 temps+maxstack # mc for methods with islarge flag turned on 32 size = 12 + w_method.islarge * 20 + w_method.argsize - w_result = space.classtable['w_MethodContext'].as_class_get_shadow(space).new(size) + w_result = space.w_MethodContext.as_class_get_shadow(space).new(size) assert isinstance(w_result, model.W_PointersObject) # create and attach a shadow manually, to not have to carefully put things # into the right places in the W_PointersObject Modified: pypy/trunk/pypy/translator/goal/targetimageloadingsmalltalk.py ============================================================================== --- pypy/trunk/pypy/translator/goal/targetimageloadingsmalltalk.py (original) +++ pypy/trunk/pypy/translator/goal/targetimageloadingsmalltalk.py Wed Feb 25 14:45:01 2009 @@ -41,14 +41,15 @@ print w_result.as_string() return 0 +from pypy.lang.smalltalk import objspace +space = objspace.ObjSpace() + def entry_point(argv): if len(argv) > 1: filename = argv[1] else: print "usage:", argv[0], "" return -1 - from pypy.lang.smalltalk import objspace - space = objspace.ObjSpace() reader = squeakimage.ImageReader(space, squeakimage.Stream(DummyFile(filename))) reader.initialize() image = squeakimage.SqueakImage() From cfbolz at codespeak.net Wed Feb 25 14:45:54 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Feb 2009 14:45:54 +0100 (CET) Subject: [pypy-svn] r62141 - pypy/branch/spy-graphic Message-ID: <20090225134554.940C016842F@codespeak.net> Author: cfbolz Date: Wed Feb 25 14:45:54 2009 New Revision: 62141 Removed: pypy/branch/spy-graphic/ Log: remove branch because there were fixes on spy on the trunk. From cfbolz at codespeak.net Wed Feb 25 14:46:29 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Feb 2009 14:46:29 +0100 (CET) Subject: [pypy-svn] r62142 - pypy/branch/spy-graphic Message-ID: <20090225134629.88CCF168431@codespeak.net> Author: cfbolz Date: Wed Feb 25 14:46:28 2009 New Revision: 62142 Added: pypy/branch/spy-graphic/ - copied from r62141, pypy/trunk/pypy/ Log: branch again From cfbolz at codespeak.net Wed Feb 25 14:51:57 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Feb 2009 14:51:57 +0100 (CET) Subject: [pypy-svn] r62143 - pypy/branch/spy-graphic Message-ID: <20090225135157.496A3168457@codespeak.net> Author: cfbolz Date: Wed Feb 25 14:51:56 2009 New Revision: 62143 Removed: pypy/branch/spy-graphic/ Log: nonsense From cfbolz at codespeak.net Wed Feb 25 14:52:10 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Feb 2009 14:52:10 +0100 (CET) Subject: [pypy-svn] r62144 - pypy/branch/spy-graphic Message-ID: <20090225135210.AE18116849C@codespeak.net> Author: cfbolz Date: Wed Feb 25 14:52:10 2009 New Revision: 62144 Added: pypy/branch/spy-graphic/ - copied from r62143, pypy/trunk/ Log: better From witulski at codespeak.net Wed Feb 25 15:15:08 2009 From: witulski at codespeak.net (witulski at codespeak.net) Date: Wed, 25 Feb 2009 15:15:08 +0100 (CET) Subject: [pypy-svn] r62145 - pypy/branch/spy-graphic/pypy/lang/smalltalk Message-ID: <20090225141508.498EF16849E@codespeak.net> Author: witulski Date: Wed Feb 25 15:15:06 2009 New Revision: 62145 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/constants.py pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Log: (witulski, cfbolz): properly use ovfcheck_lshift for overflow detection of left-shifting. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/constants.py Wed Feb 25 15:15:06 2009 @@ -1,5 +1,3 @@ -from pypy.rlib.rarithmetic import LONG_BIT - # ___________________________________________________________________________ # Slot Names @@ -131,5 +129,6 @@ "smalltalkdict" : SO_SMALLTALK, } +LONG_BIT = 32 TAGGED_MAXINT = 2 ** (LONG_BIT - 2) - 1 TAGGED_MININT = -2 ** (LONG_BIT - 2) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Wed Feb 25 15:15:06 2009 @@ -200,22 +200,12 @@ # left shift, must fail if we lose bits beyond 32 if argument > 0: - shifted = receiver << argument - - # Make sure we respect our bitlimits set by TAGGED_XXXINT. - if shifted < 0: - # If negative, check if there are no bits unset outside the MAXINT - # region - if constants.TAGGED_MININT ^ shifted > constants.TAGGED_MAXINT: - raise PrimitiveFailedError() - else: - # If possitive, check if there are no bits set outside the MAXINT - # region - if shifted & constants.TAGGED_MAXINT != shifted: - raise PrimitiveFailedError() - + try: + shifted = rarithmetic.ovfcheck_lshift(receiver, argument) + except OverflowError: + raise PrimitiveFailedError() return interp.space.wrap_int(shifted) - + # right shift, ok to lose bits else: return interp.space.wrap_int(receiver >> -argument) From witulski at codespeak.net Wed Feb 25 15:23:34 2009 From: witulski at codespeak.net (witulski at codespeak.net) Date: Wed, 25 Feb 2009 15:23:34 +0100 (CET) Subject: [pypy-svn] r62146 - pypy/branch/spy-graphic/pypy/lang/smalltalk/test Message-ID: <20090225142334.63F8B16849E@codespeak.net> Author: witulski Date: Wed Feb 25 15:23:33 2009 New Revision: 62146 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_miniimage.py Log: (witulski, cfbolz): making the test fail for a real reason (as opposed to a stupid reason). Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_miniimage.py Wed Feb 25 15:23:33 2009 @@ -218,11 +218,11 @@ def test_runimage(): py.test.skip("This method actually runs an image. Fails since no graphical primitives yet") from pypy.lang.smalltalk import wrapper - ap = wrapper.ProcessWraper(wrapper.scheduler().active_process()) - s_ctx = ap.suspended_context().as_methodcontext_get_shadow() + ap = wrapper.ProcessWrapper(space, wrapper.scheduler(space).active_process()) + s_ctx = ap.suspended_context().as_methodcontext_get_shadow(space) ap.store_suspended_context(space.w_nil) - interp = interpreter.Interpreter() + interp = interpreter.Interpreter(space) interp.store_w_active_context(s_ctx.w_self()) interp.interpret() From arigo at codespeak.net Wed Feb 25 16:19:58 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 16:19:58 +0100 (CET) Subject: [pypy-svn] r62147 - in pypy/branch/pyjitpl5/pypy: jit/metainterp jit/tl module/pypyjit Message-ID: <20090225151958.545BC168447@codespeak.net> Author: arigo Date: Wed Feb 25 16:19:57 2009 New Revision: 62147 Added: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Log: Build a minimal jit/tl/pypyjit.py starting a PyPy translation with the jit enabled. Temporary. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Wed Feb 25 16:19:57 2009 @@ -23,6 +23,9 @@ interp, graph = get_interpreter(function, args, backendopt=backendopt, inline_threshold=0) clear_tcache() + return jittify_and_run(interp, graph) + +def jittify_and_run(interp, graph): translator = interp.typer.annotator.translator warmrunnerdesc = WarmRunnerDesc(translator, **kwds) warmrunnerdesc.state.set_param_threshold(3) # for tests Added: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Wed Feb 25 16:19:57 2009 @@ -0,0 +1,72 @@ +""" +A temporary file that invokes translation of PyPy with the JIT enabled. +""" + +import py, os + +from pypy.objspace.std import Space +from pypy.config.translationoption import set_opt_level +from pypy.config.pypyoption import get_pypy_config, set_pypy_opt_level + +config = get_pypy_config(translating=True) +set_opt_level(config, level='1') +config.objspace.compiler = 'ast' +config.objspace.nofaking = True +config.objspace.allworkingmodules = False +config.objspace.usemodules.pypyjit = True +set_pypy_opt_level(config, level='0') +print config + +space = Space(config) +w_dict = space.newdict() + + +def readfile(filename): + fd = os.open(filename, os.O_RDONLY, 0) + blocks = [] + while True: + data = os.read(fd, 4096) + if not data: + break + blocks.append(data) + os.close(fd) + return ''.join(blocks) + +def entry_point(): + source = readfile('pypyjit_demo.py') + ec = space.getexecutioncontext() + code = ec.compiler.compile(source, '?', 'exec', 0) + code.exec_code(space, w_dict, w_dict) + + +def test_run_translation(): + from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy + from pypy.rpython.test.test_llinterp import get_interpreter + + # first annotate, rtype, and backendoptimize PyPy + interp, graph = get_interpreter(entry_point, [], backendopt=True, + config=config, + policy=PyPyAnnotatorPolicy(space)) + + # parent process loop: spawn a child, wait for the child to finish, + # print a message, and restart + while True: + child_pid = os.fork() + if child_pid == 0: + break + os.waitpid(child_pid, 0) + print '-' * 79 + print 'Child process finished, press Enter to restart...' + raw_input() + + from pypy.jit.tl.pypyjit_child import run_child + run_child(globals(), locals()) + + +if __name__ == '__main__': + import sys + if len(sys.argv) > 1: + # debugging: run the code directly + entry_point() + else: + test_run_translation() Added: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Wed Feb 25 16:19:57 2009 @@ -0,0 +1,4 @@ + + +def run_child(glob, loc): + xxx Added: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Wed Feb 25 16:19:57 2009 @@ -0,0 +1,2 @@ + +print 6 * 7 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Wed Feb 25 16:19:57 2009 @@ -19,7 +19,7 @@ from pypy.interpreter.pyopcode import Return, Yield -Frame._virtualizable_ = True +#Frame._virtualizable2_ = True PyCode.jit_enable = False # new default attribute super_dispatch = PyFrame.dispatch @@ -29,14 +29,14 @@ if pycode.jit_enable: return self.dispatch_jit(pycode, next_instr, ec) else: - self = hint(self, access_directly=True) + #self = hint(self, access_directly=True) return super_dispatch(self, pycode, next_instr, ec) def dispatch_jit(self, pycode, next_instr, ec): - hint(None, global_merge_point=True) - pycode = hint(pycode, deepfreeze=True) + #hint(None, global_merge_point=True) + #pycode = hint(pycode, deepfreeze=True) - entry_fastlocals_w = self.jit_enter_frame(pycode, next_instr) + #entry_fastlocals_w = self.jit_enter_frame(pycode, next_instr) # For the sequel, force 'next_instr' to be unsigned for performance next_instr = r_uint(next_instr) @@ -58,89 +58,89 @@ finally: self.jit_leave_frame(pycode, entry_fastlocals_w) - def jit_enter_frame(self, pycode, next_instr): - # *loads* of nonsense for now +## def jit_enter_frame(self, pycode, next_instr): +## # *loads* of nonsense for now - fastlocals_w = [None] * pycode.co_nlocals +## fastlocals_w = [None] * pycode.co_nlocals - if next_instr == 0: - # first time we enter this function - depth = 0 - self.blockstack = [] - - numargs = pycode.co_argcount - if pycode.co_flags & CO_VARARGS: numargs += 1 - if pycode.co_flags & CO_VARKEYWORDS: numargs += 1 - while True: - numargs -= 1 - if numargs < 0: - break - hint(numargs, concrete=True) - w_obj = self.fastlocals_w[numargs] - assert w_obj is not None - fastlocals_w[numargs] = w_obj +## if next_instr == 0: +## # first time we enter this function +## depth = 0 +## self.blockstack = [] + +## numargs = pycode.co_argcount +## if pycode.co_flags & CO_VARARGS: numargs += 1 +## if pycode.co_flags & CO_VARKEYWORDS: numargs += 1 +## while True: +## numargs -= 1 +## if numargs < 0: +## break +## hint(numargs, concrete=True) +## w_obj = self.fastlocals_w[numargs] +## assert w_obj is not None +## fastlocals_w[numargs] = w_obj + +## else: +## stuff = self.valuestackdepth +## if len(self.blockstack): +## stuff |= (-sys.maxint-1) + +## stuff = hint(stuff, promote=True) +## if stuff >= 0: +## # blockdepth == 0, common case +## self.blockstack = [] +## depth = stuff & sys.maxint + +## i = pycode.co_nlocals +## while True: +## i -= 1 +## if i < 0: +## break +## hint(i, concrete=True) +## w_obj = self.fastlocals_w[i] +## fastlocals_w[i] = w_obj + +## self.pycode = pycode +## self.valuestackdepth = depth + +## entry_fastlocals_w = self.fastlocals_w +## self.fastlocals_w = fastlocals_w + +## virtualstack_w = [None] * pycode.co_stacksize +## while depth > 0: +## depth -= 1 +## hint(depth, concrete=True) +## virtualstack_w[depth] = self.valuestack_w[depth] +## self.valuestack_w = virtualstack_w +## return entry_fastlocals_w + +## def jit_leave_frame(self, pycode, entry_fastlocals_w): +## i = pycode.co_nlocals +## while True: +## i -= 1 +## if i < 0: +## break +## hint(i, concrete=True) +## entry_fastlocals_w[i] = self.fastlocals_w[i] - else: - stuff = self.valuestackdepth - if len(self.blockstack): - stuff |= (-sys.maxint-1) - - stuff = hint(stuff, promote=True) - if stuff >= 0: - # blockdepth == 0, common case - self.blockstack = [] - depth = stuff & sys.maxint - - i = pycode.co_nlocals - while True: - i -= 1 - if i < 0: - break - hint(i, concrete=True) - w_obj = self.fastlocals_w[i] - fastlocals_w[i] = w_obj - - self.pycode = pycode - self.valuestackdepth = depth - - entry_fastlocals_w = self.fastlocals_w - self.fastlocals_w = fastlocals_w - - virtualstack_w = [None] * pycode.co_stacksize - while depth > 0: - depth -= 1 - hint(depth, concrete=True) - virtualstack_w[depth] = self.valuestack_w[depth] - self.valuestack_w = virtualstack_w - return entry_fastlocals_w - - def jit_leave_frame(self, pycode, entry_fastlocals_w): - i = pycode.co_nlocals - while True: - i -= 1 - if i < 0: - break - hint(i, concrete=True) - entry_fastlocals_w[i] = self.fastlocals_w[i] - - self.fastlocals_w = entry_fastlocals_w +## self.fastlocals_w = entry_fastlocals_w PORTAL = PyFrame.dispatch_jit -class __extend__(Function): - __metaclass__ = extendabletype +##class __extend__(Function): +## __metaclass__ = extendabletype - def getcode(self): - # if the self is a compile time constant and if its code - # is a BuiltinCode => grab and return its code as a constant - if _is_early_constant(self): - from pypy.interpreter.gateway import BuiltinCode - code = hint(self, deepfreeze=True).code - if not isinstance(code, BuiltinCode): code = self.code - else: - code = self.code - return code +## def getcode(self): +## # if the self is a compile time constant and if its code +## # is a BuiltinCode => grab and return its code as a constant +## if _is_early_constant(self): +## from pypy.interpreter.gateway import BuiltinCode +## code = hint(self, deepfreeze=True).code +## if not isinstance(code, BuiltinCode): code = self.code +## else: +## code = self.code +## return code # ____________________________________________________________ @@ -152,7 +152,7 @@ # code backend can fish for it - XXX the following import will look # less obscure once codebuf.py is moved to a general # processor-independent place - from pypy.jit.codegen.hlinfo import highleveljitinfo + from pypy.jit.backend.hlinfo import highleveljitinfo if highleveljitinfo.sys_executable is None: highleveljitinfo.sys_executable = space.str_w( space.sys.get('executable')) From arigo at codespeak.net Wed Feb 25 16:20:40 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 16:20:40 +0100 (CET) Subject: [pypy-svn] r62148 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225152040.7137B1683F2@codespeak.net> Author: arigo Date: Wed Feb 25 16:20:39 2009 New Revision: 62148 Removed: pypy/branch/pyjitpl5/pypy/module/pypyjit/newbool.py Log: Kill old module. From arigo at codespeak.net Wed Feb 25 16:54:44 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 16:54:44 +0100 (CET) Subject: [pypy-svn] r62149 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090225155444.361201684C9@codespeak.net> Author: arigo Date: Wed Feb 25 16:54:42 2009 New Revision: 62149 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Support for we_are_jitted(). Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Wed Feb 25 16:54:42 2009 @@ -3,6 +3,7 @@ from pypy.objspace.flow.model import Variable, Constant, Link, c_last_exception from pypy.rlib import objectmodel from pypy.rlib.objectmodel import we_are_translated +from pypy.rlib.jit import _we_are_jitted from pypy.jit.metainterp.history import Const, getkind, getkind_num from pypy.jit.metainterp import heaptracker, support, history @@ -243,6 +244,7 @@ """Generate a constant of the given value. Returns its index in the list self.positions[]. """ + if constvalue is _we_are_jitted: constvalue = True const = Const._new(constvalue, self.cpu) return self.get_position(const) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Wed Feb 25 16:54:42 2009 @@ -1,5 +1,5 @@ import py -from pypy.rlib.jit import JitDriver +from pypy.rlib.jit import JitDriver, we_are_jitted from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp import support, codewriter, pyjitpl, history @@ -201,6 +201,22 @@ assert res == 42 self.check_loops(int_mul=1, int_mod=0) + def test_we_are_jitted(self): + myjitdriver = JitDriver(greens = [], reds = ['y']) + def f(y): + while y >= 0: + myjitdriver.can_enter_jit(y=y) + myjitdriver.jit_merge_point(y=y) + if we_are_jitted(): + x = 1 + else: + x = 10 + y -= x + return y + assert f(55) == -5 + res = self.meta_interp(f, [55]) + assert res == -1 + class TestOOtype(BasicTests, OOJitMixin): pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Wed Feb 25 16:54:42 2009 @@ -23,9 +23,9 @@ interp, graph = get_interpreter(function, args, backendopt=backendopt, inline_threshold=0) clear_tcache() - return jittify_and_run(interp, graph) + return jittify_and_run(interp, graph, args, **kwds) -def jittify_and_run(interp, graph): +def jittify_and_run(interp, graph, args, **kwds): translator = interp.typer.annotator.translator warmrunnerdesc = WarmRunnerDesc(translator, **kwds) warmrunnerdesc.state.set_param_threshold(3) # for tests From arigo at codespeak.net Wed Feb 25 17:00:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:00:48 +0100 (CET) Subject: [pypy-svn] r62150 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225160048.3718F1684C9@codespeak.net> Author: arigo Date: Wed Feb 25 17:00:46 2009 New Revision: 62150 Removed: pypy/branch/pyjitpl5/pypy/module/pypyjit/ Log: Delete the module/pypyjit, because I realized that there is a more recent version on the oo-jit branch. From arigo at codespeak.net Wed Feb 25 17:01:10 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:01:10 +0100 (CET) Subject: [pypy-svn] r62151 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225160110.E1C811684F2@codespeak.net> Author: arigo Date: Wed Feb 25 17:01:09 2009 New Revision: 62151 Added: pypy/branch/pyjitpl5/pypy/module/pypyjit/ - copied from r62149, pypy/branch/oo-jit/pypy/module/pypyjit/ Log: Copy from the oo-jit branch. From arigo at codespeak.net Wed Feb 25 17:01:56 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:01:56 +0100 (CET) Subject: [pypy-svn] r62152 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225160156.8D1211684C9@codespeak.net> Author: arigo Date: Wed Feb 25 17:01:55 2009 New Revision: 62152 Removed: pypy/branch/pyjitpl5/pypy/module/pypyjit/newbool.py Log: Kill kill again!!!! From arigo at codespeak.net Wed Feb 25 17:09:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:09:37 +0100 (CET) Subject: [pypy-svn] r62153 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225160937.4D1961684C9@codespeak.net> Author: arigo Date: Wed Feb 25 17:09:37 2009 New Revision: 62153 Removed: pypy/branch/pyjitpl5/pypy/module/pypyjit/ Log: Argh. Thanks for cfbolz, I understand what is going on now... From arigo at codespeak.net Wed Feb 25 17:11:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:11:37 +0100 (CET) Subject: [pypy-svn] r62154 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225161137.D2CC216849C@codespeak.net> Author: arigo Date: Wed Feb 25 17:11:37 2009 New Revision: 62154 Added: pypy/branch/pyjitpl5/pypy/module/pypyjit/ - copied from r61847, pypy/branch/oo-jit/pypy/module/pypyjit/ Log: Re-re-copy 'pypyjit' from the oo-jit branch, at revision r61847. In the next revision it was reverted to the state on the trunk... From arigo at codespeak.net Wed Feb 25 17:12:09 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:12:09 +0100 (CET) Subject: [pypy-svn] r62155 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225161209.43FFE1684F2@codespeak.net> Author: arigo Date: Wed Feb 25 17:12:08 2009 New Revision: 62155 Removed: pypy/branch/pyjitpl5/pypy/module/pypyjit/newbool.py Log: Kill a 3rd time. Maybe now it will really be dead. From cfbolz at codespeak.net Wed Feb 25 17:17:50 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Feb 2009 17:17:50 +0100 (CET) Subject: [pypy-svn] r62156 - pypy/trunk/pypy/objspace/std/test Message-ID: <20090225161750.6FAA71684F3@codespeak.net> Author: cfbolz Date: Wed Feb 25 17:17:49 2009 New Revision: 62156 Modified: pypy/trunk/pypy/objspace/std/test/test_typeobject.py Log: Kill some *very* old commented out code. Modified: pypy/trunk/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_typeobject.py Wed Feb 25 17:17:49 2009 @@ -2,59 +2,6 @@ from pypy.objspace.std.stdtypedef import * from pypy.conftest import gettestobjspace -##class TestSpecialMultimethodCode(testit.TestCase): - -## def setUp(self): -## self.space = testit.objspace('std') - -## def tearDown(self): -## pass - -## def test_int_sub(self): -## w = self.space.wrap -## for i in range(2): -## meth = SpecialMultimethodCode(self.space.sub.multimethod, -## self.space.w_int.__class__, i) -## self.assertEqual(meth.slice().is_empty(), False) -## # test int.__sub__ and int.__rsub__ -## self.assertEqual_w(meth.eval_code(self.space, None, -## w({'x1': 5, 'x2': 7})), -## w(-2)) -## self.assertEqual_w(meth.eval_code(self.space, None, -## w({'x1': 5, 'x2': 7.1})), -## self.space.w_NotImplemented) -## self.assertEqual_w(meth.eval_code(self.space, None, -## w({'x1': 5.5, 'x2': 7})), -## self.space.w_NotImplemented) - -## def test_empty_inplace_add(self): -## for i in range(2): -## meth = SpecialMultimethodCode(self.space.inplace_add.multimethod, -## self.space.w_int.__class__, i) -## self.assertEqual(meth.slice().is_empty(), True) - -## def test_float_sub(self): -## w = self.space.wrap -## w(1.5) # force floatobject imported -## for i in range(2): -## meth = SpecialMultimethodCode(self.space.sub.multimethod, -## self.space.w_float.__class__, i) -## self.assertEqual(meth.slice().is_empty(), False) -## # test float.__sub__ and float.__rsub__ - -## # some of these tests are pointless for Python because -## # float.__(r)sub__ should not accept an int as first argument -## self.assertEqual_w(meth.eval_code(self.space, None, -## w({'x1': 5, 'x2': 7})), -## w(-2.0)) -## self.assertEqual_w(meth.eval_code(self.space, None, -## w({'x1': 5, 'x2': 7.5})), -## w(-2.5)) -## self.assertEqual_w(meth.eval_code(self.space, None, -## w({'x1': 5.5, 'x2': 7})), -## w(-1.5)) - - class TestTypeObject: def test_not_acceptable_as_base_class(self): From arigo at codespeak.net Wed Feb 25 17:20:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:20:32 +0100 (CET) Subject: [pypy-svn] r62157 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225162032.C610E1684F4@codespeak.net> Author: arigo Date: Wed Feb 25 17:20:32 2009 New Revision: 62157 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Log: Port this interp_jit.py to the new model. Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Wed Feb 25 17:20:32 2009 @@ -6,7 +6,7 @@ import sys from pypy.tool.pairtype import extendabletype from pypy.rlib.rarithmetic import r_uint, intmask -from pypy.rlib.jit import hint, _is_early_constant, JitDriver +from pypy.rlib.jit import JitDriver import pypy.interpreter.pyopcode # for side-effects from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import ObjSpace, Arguments @@ -14,10 +14,10 @@ from pypy.interpreter.pycode import PyCode, CO_VARARGS, CO_VARKEYWORDS from pypy.interpreter.pyframe import PyFrame from pypy.interpreter.function import Function -from pypy.interpreter.pyopcode import Return, Yield +from pypy.interpreter.pyopcode import ExitFrame -Frame._virtualizable_ = True +#Frame._virtualizable2_ = True PyCode.jit_enable = False # new default attribute super_dispatch = PyFrame.dispatch @@ -25,44 +25,13 @@ reds = ['frame', 'ec'] greens = ['next_instr', 'pycode'] - def compute_invariants(self, reds, next_instr, pycode): - # compute the information that really only depends on next_instr - # and pycode - frame = reds.frame - valuestackdepth = frame.valuestackdepth - blockstack = frame.blockstack - return (valuestackdepth, blockstack) - - def on_enter_jit(self, invariants, reds, next_instr, pycode): - # *loads* of nonsense for now - (depth, oldblockstack) = invariants - frame = reds.frame - pycode = hint(pycode, deepfreeze=True) - - fastlocals_w = [None] * pycode.co_nlocals - - i = pycode.co_nlocals - while True: - i -= 1 - if i < 0: - break - hint(i, concrete=True) - w_obj = frame.fastlocals_w[i] - fastlocals_w[i] = w_obj - - frame.pycode = pycode - frame.valuestackdepth = depth - - frame.fastlocals_w = fastlocals_w - - virtualstack_w = [None] * pycode.co_stacksize - while depth > 0: - depth -= 1 - hint(depth, concrete=True) - virtualstack_w[depth] = frame.valuestack_w[depth] - frame.valuestack_w = virtualstack_w - - # XXX we should also make a completely virtual copy of oldblockstack +## def compute_invariants(self, reds, next_instr, pycode): +## # compute the information that really only depends on next_instr +## # and pycode +## frame = reds.frame +## valuestackdepth = frame.valuestackdepth +## blockstack = frame.blockstack +## return (valuestackdepth, blockstack) pypyjitdriver = PyPyJitDriver() @@ -70,21 +39,14 @@ def dispatch(self, pycode, next_instr, ec): next_instr = r_uint(next_instr) + co_code = pycode.co_code try: while True: pypyjitdriver.jit_merge_point( frame=self, ec=ec, next_instr=next_instr, pycode=pycode) - pycode = hint(pycode, deepfreeze=True) - co_code = pycode.co_code next_instr = self.handle_bytecode(co_code, next_instr, ec) - except Return: - w_result = self.popvalue() - self.blockstack = None - self.valuestack_w = None - return w_result - except Yield: - w_result = self.popvalue() - return w_result + except ExitFrame: + return self.popvalue() def JUMP_ABSOLUTE(f, jumpto, next_instr, *ignored): ec = f.space.getexecutioncontext() @@ -92,19 +54,19 @@ pycode=f.getcode()) return jumpto -class __extend__(Function): - __metaclass__ = extendabletype +##class __extend__(Function): +## __metaclass__ = extendabletype - def getcode(self): - # if the self is a compile time constant and if its code - # is a BuiltinCode => grab and return its code as a constant - if _is_early_constant(self): - from pypy.interpreter.gateway import BuiltinCode - code = hint(self, deepfreeze=True).code - if not isinstance(code, BuiltinCode): code = self.code - else: - code = self.code - return code +## def getcode(self): +## # if the self is a compile time constant and if its code +## # is a BuiltinCode => grab and return its code as a constant +## if _is_early_constant(self): +## from pypy.interpreter.gateway import BuiltinCode +## code = hint(self, deepfreeze=True).code +## if not isinstance(code, BuiltinCode): code = self.code +## else: +## code = self.code +## return code # ____________________________________________________________ @@ -114,7 +76,7 @@ def jit_startup(space, argv): # save the app-level sys.executable in JITInfo, where the machine # code backend can fish for it. A bit hackish. - from pypy.jit.codegen.hlinfo import highleveljitinfo + from pypy.jit.backend.hlinfo import highleveljitinfo highleveljitinfo.sys_executable = argv[0] # recognize the option --jit PARAM=VALUE,PARAM=VALUE... From cfbolz at codespeak.net Wed Feb 25 17:28:00 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 25 Feb 2009 17:28:00 +0100 (CET) Subject: [pypy-svn] r62158 - in pypy/trunk/pypy: interpreter/test objspace/std objspace/std/test Message-ID: <20090225162800.818D316840F@codespeak.net> Author: cfbolz Date: Wed Feb 25 17:27:59 2009 New Revision: 62158 Modified: pypy/trunk/pypy/interpreter/test/test_exceptcomp.py pypy/trunk/pypy/objspace/std/intobject.py pypy/trunk/pypy/objspace/std/stdtypedef.py pypy/trunk/pypy/objspace/std/test/test_intobject.py pypy/trunk/pypy/objspace/std/test/test_stringobject.py Log: Clean up some commented out and very old code. Kill a completely outdated comment. Modified: pypy/trunk/pypy/interpreter/test/test_exceptcomp.py ============================================================================== --- pypy/trunk/pypy/interpreter/test/test_exceptcomp.py (original) +++ pypy/trunk/pypy/interpreter/test/test_exceptcomp.py Wed Feb 25 17:27:59 2009 @@ -5,32 +5,6 @@ class AppTestExceptionComp: -### XXX - String exceptions depreciated? -## def test_string(self): -## string = "string" -## try: -## raise string -## except string: -## pass -## except: -## self.fail("Identical string exceptions do not match.") -## -## def test_stringfail(self): -## string1 = "string1" -## string1_ = "string" + "1" -## assert string1 is not string1_ -## try: -## raise string1 -## except "string2": -## self.fail("Different string exceptions match.") -## except string1_: -## self.fail("Non Identical string exceptions match.") -## except string1: -## pass -## except: -## self.fail("Unknown value for variable raise.") - - def test_exception(self): try: raise TypeError, "nothing" Modified: pypy/trunk/pypy/objspace/std/intobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/intobject.py (original) +++ pypy/trunk/pypy/objspace/std/intobject.py Wed Feb 25 17:27:59 2009 @@ -247,20 +247,8 @@ if b >= LONG_BIT: raise FailedToImplement(space.w_OverflowError, space.wrap("integer left shift")) - ## - ## XXX please! have a look into pyport.h and see how to implement - ## the overflow checking, using macro Py_ARITHMETIC_RIGHT_SHIFT - ## we *assume* that the overflow checking is done correctly - ## in the code generator, which is not trivial! - - ## XXX also note that Python 2.3 returns a long and never raises - ## OverflowError. try: c = ovfcheck_lshift(a, b) - ## the test in C code is - ## if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) { - ## if (PyErr_Warn(PyExc_FutureWarning, - # and so on except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer left shift")) @@ -280,8 +268,6 @@ else: a = 0 else: - ## please look into pyport.h, how >> should be implemented! - ## a = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); a = a >> b return wrapint(space, a) Modified: pypy/trunk/pypy/objspace/std/stdtypedef.py ============================================================================== --- pypy/trunk/pypy/objspace/std/stdtypedef.py (original) +++ pypy/trunk/pypy/objspace/std/stdtypedef.py Wed Feb 25 17:27:59 2009 @@ -110,46 +110,6 @@ result.append(value) return result -##def make_frameclass_for_arity(arity, varargs, keywords, isspecial): -## argnames = [] -## for i in range(arity): -## argnames.append('arg%dof%d'%(i+1, arity)) -## if varargs: -## argnames.append('var_args') -## if keywords: -## argnames.append('kw_args') -## self_args_assigning = [] -## for i in range(len(argnames)): -## self_args_assigning.append(' self.%s = args[%i]'%(argnames[i], i)) -## self_args_assigning = "\n".join(self_args_assigning) -## self_args = ", ".join(['self.'+ a for a in argnames]) -## name = 'MmFrameOfArity%d'%arity -## if varargs: -## name += "Var" -## if keywords: -## name += "KW" -## if isspecial: -## name = "Special" + name -## d = locals() -## template = mmtemplate -## if isspecial: -## template += specialmmruntemplate -## else: -## template += mmruntemplate -### print template%d -## exec template%d in globals(), d -## return d[name] -## -##_frameclass_for_arity_cache = {} -##def frameclass_for_arity(arity, varargs, keywords, isspecial): -## try: -## return _frameclass_for_arity_cache[(arity, varargs, keywords, isspecial)] -## except KeyError: -## r = _frameclass_for_arity_cache[(arity, varargs, keywords, isspecial)] = \ -## make_frameclass_for_arity(arity, varargs, keywords, isspecial) -## return r - - def sliced_typeorders(typeorder, multimethod, typedef, i, local=False): """NOT_RPYTHON""" list_of_typeorders = [typeorder] * multimethod.arity Modified: pypy/trunk/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_intobject.py Wed Feb 25 17:27:59 2009 @@ -271,18 +271,6 @@ result = iobj.int__Int(self.space, f1) assert result == f1 -## def test_long(self): -## x = 1 -## f1 = iobj.W_IntObject(x) -## result = iobj.int_long(self.space, f1) -## self.assertEquals(self.space.unwrap(result), long(x)) - -## def test_float(self): -## x = 1 -## f1 = iobj.W_IntObject(x) -## result = iobj.int_float(self.space, f1) -## self.assertEquals(self.space.unwrap(result), float(x)) - def test_oct(self): x = 012345 f1 = iobj.W_IntObject(x) Modified: pypy/trunk/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/trunk/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/trunk/pypy/objspace/std/test/test_stringobject.py Wed Feb 25 17:27:59 2009 @@ -8,34 +8,6 @@ def teardown_method(self, method): pass -## def test_order_rich(self): -## space = self.space -## def w(txt): -## return W_StringObject(space, txt) -## strs = ['ala', 'bla', 'ala', 'alaaa', '', 'b'] -## ops = [ 'EQ', 'LT', 'GT', 'NE', 'LE', 'GE' ] - -## while strs[1:]: -## str1 = strs.pop() -## for op in ops: -## #original python function -## orf = getattr(str1, '__%s__' % op.lower()) -## pypyconst = getattr(stringobject, op) -## for str2 in strs: -## if orf(str2): -## self.failUnless_w( -## string_richcompare(space, -## w(str1), -## w(str2), -## pypyconst)) -## else: -## self.failIf_w( -## string_richcompare(space, -## w(str1), -## w(str2), -## pypyconst)) - - def test_str_w(self): assert self.space.str_w(self.space.wrap("foo")) == "foo" From arigo at codespeak.net Wed Feb 25 17:33:05 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:33:05 +0100 (CET) Subject: [pypy-svn] r62159 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225163305.5E2A016842F@codespeak.net> Author: arigo Date: Wed Feb 25 17:33:04 2009 New Revision: 62159 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Log: This attribute is no longer used. Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Wed Feb 25 17:33:04 2009 @@ -18,7 +18,6 @@ #Frame._virtualizable2_ = True -PyCode.jit_enable = False # new default attribute super_dispatch = PyFrame.dispatch class PyPyJitDriver(JitDriver): From arigo at codespeak.net Wed Feb 25 17:33:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 17:33:30 +0100 (CET) Subject: [pypy-svn] r62160 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225163330.035311684EE@codespeak.net> Author: arigo Date: Wed Feb 25 17:33:30 2009 New Revision: 62160 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Log: ...and while we're at it, neither is that. Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Wed Feb 25 17:33:30 2009 @@ -18,7 +18,6 @@ #Frame._virtualizable2_ = True -super_dispatch = PyFrame.dispatch class PyPyJitDriver(JitDriver): reds = ['frame', 'ec'] From arigo at codespeak.net Wed Feb 25 18:49:48 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 18:49:48 +0100 (CET) Subject: [pypy-svn] r62161 - in pypy/branch/pyjitpl5/pypy: jit/tl rpython/lltypesystem Message-ID: <20090225174948.248FD1684FD@codespeak.net> Author: arigo Date: Wed Feb 25 18:49:48 2009 New Revision: 62161 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py Log: Slight improvement to pypyjit_child. Fix in lltype.py to handle freed arrays in the _subarray._cache. Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Wed Feb 25 18:49:48 2009 @@ -1,4 +1,15 @@ +from pypy.rpython.lltypesystem import lltype +from pypy.jit.metainterp import warmspot def run_child(glob, loc): - xxx + interp = loc['interp'] + graph = loc['graph'] + interp.malloc_check = False + + def returns_null(T, *args, **kwds): + return lltype.nullptr(T) + interp.heap.malloc_nonmovable = returns_null # XXX + + print 'warmspot.jittify_and_run() started...' + warmspot.jittify_and_run(interp, graph, []) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Wed Feb 25 18:49:48 2009 @@ -1,2 +1,5 @@ -print 6 * 7 +i = 0 +while i < 100: + i += 3 +print i # should print 102 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lltype.py Wed Feb 25 18:49:48 2009 @@ -1570,7 +1570,11 @@ self._parentstructure().setitem(baseoffset + index, value) def _makeptr(parent, baseoffset_or_fieldname, solid=False): - cache = _subarray._cache.setdefault(parent, {}) + try: + cache = _subarray._cache.setdefault(parent, {}) + except RuntimeError: # pointer comparison with a freed structure + _subarray._cleanup_cache() + cache = _subarray._cache.setdefault(parent, {}) # try again try: subarray = cache[baseoffset_or_fieldname] except KeyError: @@ -1590,6 +1594,17 @@ def _getid(self): raise NotImplementedError('_subarray._getid()') + def _cleanup_cache(): + newcache = weakref.WeakKeyDictionary() + for key, value in _subarray._cache.items(): + try: + if not key._was_freed(): + newcache[key] = value + except RuntimeError: + pass # ignore "accessing subxxx, but already gc-ed parent" + _subarray._cache = newcache + _cleanup_cache = staticmethod(_cleanup_cache) + class _arraylenref(_parentable): """Pseudo-reference to the length field of an array. From witulski at codespeak.net Wed Feb 25 18:51:56 2009 From: witulski at codespeak.net (witulski at codespeak.net) Date: Wed, 25 Feb 2009 18:51:56 +0100 (CET) Subject: [pypy-svn] r62162 - in pypy/branch/spy-graphic/pypy/lang/smalltalk: . test Message-ID: <20090225175156.0B96A16842C@codespeak.net> Author: witulski Date: Wed Feb 25 18:51:56 2009 New Revision: 62162 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/conftest.py pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py pypy/branch/spy-graphic/pypy/lang/smalltalk/squeakimage.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_wrapper.py pypy/branch/spy-graphic/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, witulski): the int getters and setters don't really need a space argument. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/conftest.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/conftest.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/conftest.py Wed Feb 25 18:51:56 2009 @@ -7,4 +7,9 @@ dest="bc_trace", default=False, help="print bytecodes and stack during execution"), - ) + Option('--prim-trace', + action="store_true", + dest="prim_trace", + default=False, + help="print called primitives during execution"), +) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py Wed Feb 25 18:51:56 2009 @@ -42,8 +42,12 @@ except ReturnFromTopLevel, e: return e.object - def should_trace(self): - return (not objectmodel.we_are_translated()) and option.bc_trace + def should_trace(self, primitives=False): + if objectmodel.we_are_translated(): + return False + if not primitives: + return option.bc_trace + return option.prim_trace def step(self): next = self.s_active_context().getNextBytecode() @@ -207,7 +211,7 @@ w_result = func(interp, argcount) return except primitives.PrimitiveFailedError: - if interp.should_trace(): + if interp.should_trace(True): print "PRIMITIVE FAILED: %d %s" % (method.primitive, selector,) pass # ignore this error and fall back to the Smalltalk version arguments = self.pop_and_return_n(argcount) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Wed Feb 25 18:51:56 2009 @@ -289,10 +289,10 @@ @expose_primitive(MAKE_POINT, unwrap_spec=[int, int]) def func(interp, x, y): - w_res = interp.space.classtable['w_Point'].as_class_get_shadow(interp.space).new(2) + w_res = interp.space.w_Point.as_class_get_shadow(interp.space).new(2) point = wrapper.PointWrapper(interp.space, w_res) - point.store_x(interp.space, x) - point.store_y(interp.space, y) + point.store_x(x) + point.store_y(y) return w_res @@ -455,6 +455,31 @@ return w_method # ___________________________________________________________________________ +# I/O Primitives + +MOUSE_POINT = 90 +TEST_DISPLAY_DEPTH = 91 +SET_DISPLAY_MODE = 92 +INPUT_SEMAPHORE = 93 +GET_NEXT_EVENT = 94 +INPUT_WORD = 95 +OBSOLETE_INDEXED_PRIMITIVE = 96 +SNAPSHOT = 97 +STORE_IMAGE_SEGMENT = 98 +LOAD_IMAGE_SEGMENT = 99 +PERFORM_IN_SUPERCLASS = 100 +BE_CURSOR = 101 +BE_DISPLAY = 102 +SCAN_CHARACTERS = 103 +OBSOLETE_INDEXED_PRIMITIVE =104 +STRING_REPLACE = 105 +SCREEN_SIZE = 106 +MOUSE_BUTTONS = 107 +KBD_NEXT = 108 +KBD_PEEK = 109 + + +# ___________________________________________________________________________ # Control Primitives EQUIVALENT = 110 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/squeakimage.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/squeakimage.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/squeakimage.py Wed Feb 25 18:51:56 2009 @@ -111,6 +111,7 @@ # 1 word last used hash lasthash = self.stream.next() savedwindowssize = self.stream.next() + print "savedwindowssize", savedwindowssize fullscreenflag = self.stream.next() extravmmemory = self.stream.next() # we called 9 times next, 1 word = 4 byte Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py Wed Feb 25 18:51:56 2009 @@ -464,8 +464,8 @@ w_point = interp.s_active_context().top() from pypy.lang.smalltalk.wrapper import PointWrapper point = PointWrapper(interp.space, w_point) - assert point.x(interp.space) == 0 - assert point.y(interp.space) == 1 + assert point.x() == 0 + assert point.y() == 1 def test_longJumpIfTrue(): interp = new_interpreter(longJumpIfTrue(0) + chr(15) + longJumpIfTrue(0) + chr(15)) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_wrapper.py Wed Feb 25 18:51:56 2009 @@ -115,7 +115,7 @@ def new_semaphore(excess_signals=0): w_semaphore = model.W_PointersObject(None, 3) semaphore = wrapper.SemaphoreWrapper(space, w_semaphore) - semaphore.store_excess_signals(space, excess_signals) + semaphore.store_excess_signals(excess_signals) return semaphore @@ -205,7 +205,7 @@ semaphore = new_semaphore() self.space = space semaphore.signal(self) - assert semaphore.excess_signals(space) == 1 + assert semaphore.excess_signals() == 1 def test_highest_priority(self): py.test.raises(FatalError, wrapper.scheduler(space).highest_priority_process) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/wrapper.py Wed Feb 25 18:51:56 2009 @@ -34,13 +34,13 @@ return make_getter(index0), make_setter(index0) def make_int_getter(index0): - def getter(self, space): - return space.unwrap_int(self.read(index0)) + def getter(self): + return self.space.unwrap_int(self.read(index0)) return getter def make_int_setter(index0): - def setter(self, space, new): - return self.write(index0, space.wrap_int(new)) + def setter(self, new): + return self.write(index0, self.space.wrap_int(new)) return setter def make_int_getter_setter(index0): @@ -186,17 +186,17 @@ def signal(self, interp): if self.is_empty_list(): - value = self.excess_signals(interp.space) - self.store_excess_signals(interp.space, value + 1) + value = self.excess_signals() + self.store_excess_signals(value + 1) else: process = self.remove_first_link_of_list() ProcessWrapper(self.space, process).resume(interp) def wait(self, interp): - excess = self.excess_signals(interp.space) + excess = self.excess_signals() w_process = scheduler(interp.space).active_process() if excess > 0: - self.store_excess_signals(interp.space, excess - 1) + self.store_excess_signals(excess - 1) else: self.add_last_link(w_process) ProcessWrapper(self.space, w_process).suspend(interp) @@ -219,6 +219,3 @@ class CursorWrapper(MaskWrapper): offset = make_getter(4) -class PointWrapper(Wrapper): - x, store_x = make_int_getter_setter(0) - y, store_y = make_int_getter_setter(1) From arigo at codespeak.net Wed Feb 25 19:16:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 25 Feb 2009 19:16:38 +0100 (CET) Subject: [pypy-svn] r62163 - pypy/branch/pyjitpl5/pypy/module/pypyjit Message-ID: <20090225181638.7F09216850D@codespeak.net> Author: arigo Date: Wed Feb 25 19:16:37 2009 New Revision: 62163 Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Log: Fix. Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/interp_jit.py Wed Feb 25 19:16:37 2009 @@ -37,11 +37,11 @@ def dispatch(self, pycode, next_instr, ec): next_instr = r_uint(next_instr) - co_code = pycode.co_code try: while True: pypyjitdriver.jit_merge_point( frame=self, ec=ec, next_instr=next_instr, pycode=pycode) + co_code = pycode.co_code next_instr = self.handle_bytecode(co_code, next_instr, ec) except ExitFrame: return self.popvalue() From tverwaes at codespeak.net Wed Feb 25 19:57:23 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 25 Feb 2009 19:57:23 +0100 (CET) Subject: [pypy-svn] r62164 - in pypy/branch/spy-graphic/pypy/lang/smalltalk: . test Message-ID: <20090225185723.6CA0516802C@codespeak.net> Author: tverwaes Date: Wed Feb 25 19:57:20 2009 New Revision: 62164 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Log: removed PRIMITIVE pre and postfixes for consistency. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py Wed Feb 25 19:57:20 2009 @@ -493,22 +493,22 @@ def bytecodePrimBlockCopy(self, interp): # the primitive checks the class of the receiver - self.callPrimitive(primitives.PRIMITIVE_BLOCK_COPY, + self.callPrimitive(primitives.BLOCK_COPY, "blockCopy:", 1, interp) def bytecodePrimValue(self, interp): # the primitive checks the class of the receiver self.callPrimitive( - primitives.PRIMITIVE_VALUE, "value", 0, interp) + primitives.VALUE, "value", 0, interp) def bytecodePrimValueWithArg(self, interp): # the primitive checks the class of the receiver - # Note that the PRIMITIVE_VALUE_WITH_ARGS takes an array of + # Note that the VALUE_WITH_ARGS takes an array of # arguments but this bytecode is about the one-argument case. - # The PRIMITIVE_VALUE is general enough to take any number of + # The VALUE is general enough to take any number of # arguments from the stack, so it's the one we need to use here. self.callPrimitive( - primitives.PRIMITIVE_VALUE, "value:", 1, interp) + primitives.VALUE, "value:", 1, interp) def bytecodePrimDo(self, interp): self._sendSelfSelector("do:", 1, interp) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Wed Feb 25 19:57:20 2009 @@ -463,7 +463,7 @@ INPUT_SEMAPHORE = 93 GET_NEXT_EVENT = 94 INPUT_WORD = 95 -OBSOLETE_INDEXED_PRIMITIVE = 96 +OBSOLETE_INDEXED = 96 SNAPSHOT = 97 STORE_IMAGE_SEGMENT = 98 LOAD_IMAGE_SEGMENT = 99 @@ -471,13 +471,23 @@ BE_CURSOR = 101 BE_DISPLAY = 102 SCAN_CHARACTERS = 103 -OBSOLETE_INDEXED_PRIMITIVE =104 +# OBSOLETE_INDEXED = 104 # also 96 STRING_REPLACE = 105 SCREEN_SIZE = 106 MOUSE_BUTTONS = 107 KBD_NEXT = 108 KBD_PEEK = 109 + at expose_primitive(BE_CURSOR, unwrap_spec=[object]) +def func(interp, w_rcvr): + # TODO: Use info from cursor object. + interp.space.objtable['w_cursor'] = w_rcvr + return w_rcvr + + at expose_primitive(BE_DISPLAY, unwrap_spec=[object]) +def func(interp, w_rcvr): + interp.space.objtable['w_display'] = w_rcvr + return w_rcvr # ___________________________________________________________________________ # Control Primitives @@ -667,18 +677,18 @@ # ___________________________________________________________________________ # Control Primitives -PRIMITIVE_BLOCK_COPY = 80 -PRIMITIVE_VALUE = 81 -PRIMITIVE_VALUE_WITH_ARGS = 82 -PRIMITIVE_PERFORM = 83 -PRIMITIVE_PERFORM_WITH_ARGS = 84 -PRIMITIVE_SIGNAL = 85 -PRIMITIVE_WAIT = 86 -PRIMITIVE_RESUME = 87 -PRIMITIVE_SUSPEND = 88 -PRIMITIVE_FLUSH_CACHE = 89 +BLOCK_COPY = 80 +VALUE = 81 +VALUE_WITH_ARGS = 82 +PERFORM = 83 +PERFORM_WITH_ARGS = 84 +SIGNAL = 85 +WAIT = 86 +RESUME = 87 +SUSPEND = 88 +FLUSH_CACHE = 89 - at expose_primitive(PRIMITIVE_BLOCK_COPY, unwrap_spec=[object, int]) + at expose_primitive(BLOCK_COPY, unwrap_spec=[object, int]) def func(interp, w_context, argcnt): frame = interp.s_active_context() @@ -703,7 +713,7 @@ s_block_ctx.store_w_sender(frame) interp.store_w_active_context(s_block_ctx.w_self()) - at expose_primitive(PRIMITIVE_VALUE, no_result=True) + at expose_primitive(VALUE, no_result=True) def func(interp, argument_count): # argument_count does NOT include the receiver. # This means that for argument_count == 3 the stack looks like: @@ -741,7 +751,7 @@ frame.pop() finalize_block_ctx(interp, s_block_ctx, frame.w_self()) - at expose_primitive(PRIMITIVE_VALUE_WITH_ARGS, unwrap_spec=[object, object], + at expose_primitive(VALUE_WITH_ARGS, unwrap_spec=[object, object], no_result=True) def func(interp, w_block_ctx, w_args): @@ -765,11 +775,11 @@ # because falls back to value + internal implementation finalize_block_ctx(interp, s_block_ctx, interp.w_active_context()) - at expose_primitive(PRIMITIVE_PERFORM) + at expose_primitive(PERFORM) def func(interp, argcount): raise PrimitiveFailedError() - at expose_primitive(PRIMITIVE_PERFORM_WITH_ARGS, + at expose_primitive(PERFORM_WITH_ARGS, unwrap_spec=[object, str, object], no_result=True) def func(interp, w_rcvr, sel, w_args): @@ -782,7 +792,7 @@ w_frame.as_context_get_shadow(interp.space).store_w_sender(interp.w_active_context()) interp.store_w_active_context(w_frame) - at expose_primitive(PRIMITIVE_SIGNAL, unwrap_spec=[object]) + at expose_primitive(SIGNAL, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( @@ -791,7 +801,7 @@ wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(interp) return w_rcvr - at expose_primitive(PRIMITIVE_WAIT, unwrap_spec=[object]) + at expose_primitive(WAIT, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( @@ -800,7 +810,7 @@ wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(interp) return w_rcvr - at expose_primitive(PRIMITIVE_RESUME, unwrap_spec=[object]) + at expose_primitive(RESUME, unwrap_spec=[object]) def func(interp, w_rcvr,): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( @@ -809,7 +819,7 @@ wrapper.ProcessWrapper(interp.space, w_rcvr).resume(interp) return w_rcvr - at expose_primitive(PRIMITIVE_SUSPEND, unwrap_spec=[object]) + at expose_primitive(SUSPEND, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( @@ -818,7 +828,7 @@ wrapper.ProcessWrapper(interp.space, w_rcvr).suspend(interp) return w_rcvr - at expose_primitive(PRIMITIVE_FLUSH_CACHE, unwrap_spec=[object]) + at expose_primitive(FLUSH_CACHE, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we currently don't care about bad flushes :) XXX # raise PrimitiveNotYetWrittenError() @@ -841,6 +851,5 @@ return w_object.fetch(interp.space, i - 264) globals()["INST_VAR_AT_%d" % (i-264)] = i make_prim(i) - unrolling_prim_table = unroll.unrolling_iterable(prim_table_implemented_only) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py Wed Feb 25 19:57:20 2009 @@ -701,7 +701,7 @@ 176, 125, 33, 34, 240, 124 ], fakeliterals(space, "value:value:", space.wrap_int(3), space.wrap_int(4))).value == 7 run_with_faked_methods( - [[space.w_BlockContext, primitives.PRIMITIVE_VALUE, + [[space.w_BlockContext, primitives.VALUE, 2, "value:value:"]], test) @@ -739,7 +739,7 @@ fakeliterals(space, "valueWithArguments:", [3, 2])).value == 1 run_with_faked_methods( - [[space.w_BlockContext, primitives.PRIMITIVE_VALUE_WITH_ARGS, + [[space.w_BlockContext, primitives.VALUE_WITH_ARGS, 1, "valueWithArguments:"]], test) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Wed Feb 25 19:57:20 2009 @@ -418,9 +418,9 @@ # primitives.NEXT is unimplemented as it is a performance optimization # primitives.NEXT_PUT is unimplemented as it is a performance optimization # primitives.AT_END is unimplemented as it is a performance optimization -# primitives.PRIMITIVE_BLOCK_COPY is tested in test_interpreter -# primitives.PRIMITIVE_VALUE is tested in test_interpreter -# primitives.PRIMITIVE_VALUE_WITH_ARGS is tested in test_interpreter +# primitives.BLOCK_COPY is tested in test_interpreter +# primitives.VALUE is tested in test_interpreter +# primitives.VALUE_WITH_ARGS is tested in test_interpreter # primitives.OBJECT_AT is tested in test_interpreter # primitives.OBJECT_AT_PUT is tested in test_interpreter From arigo at codespeak.net Thu Feb 26 11:04:28 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 11:04:28 +0100 (CET) Subject: [pypy-svn] r62174 - pypy/branch/pyjitpl5/pypy/rpython Message-ID: <20090226100428.5065A16850D@codespeak.net> Author: arigo Date: Thu Feb 26 11:04:26 2009 New Revision: 62174 Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Log: Fix an occasional KeyError in remember_free. Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Thu Feb 26 11:04:26 2009 @@ -166,7 +166,18 @@ self.mallocs[ptr._obj] = llframe def remember_free(self, ptr): - del self.mallocs[ptr._obj] + try: + del self.mallocs[ptr._obj] + except KeyError: + self._rehash_mallocs() + del self.mallocs[ptr._obj] + + def _rehash_mallocs(self): + # rehashing is needed because some objects' hash may change + # when being turned to + items = self.mallocs.items() + self.mallocs = {} + self.mallocs.update(items) def checkptr(ptr): assert isinstance(lltype.typeOf(ptr), lltype.Ptr) From arigo at codespeak.net Thu Feb 26 11:05:03 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 11:05:03 +0100 (CET) Subject: [pypy-svn] r62175 - pypy/branch/pyjitpl5/pypy/rpython/lltypesystem Message-ID: <20090226100503.E0D87168514@codespeak.net> Author: arigo Date: Thu Feb 26 11:05:03 2009 New Revision: 62175 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py Log: Some changes from the trunk have been accidentally lost in r61730. Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/ll_str.py Thu Feb 26 11:05:03 2009 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem.lltype import GcArray, Array, Char, malloc +from pypy.rpython.annlowlevel import llstr from pypy.rlib.rarithmetic import r_uint, formatd CHAR_ARRAY = GcArray(Char) @@ -119,5 +120,5 @@ ll_int2oct._pure_function_ = True def ll_float_str(repr, f): - return formatd("%f", f) + return llstr(formatd("%f", f)) ll_float_str._pure_function_ = True From arigo at codespeak.net Thu Feb 26 13:55:23 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 13:55:23 +0100 (CET) Subject: [pypy-svn] r62178 - in pypy/branch/pyjitpl5/pypy/rpython: . lltypesystem Message-ID: <20090226125523.6E8B31684D0@codespeak.net> Author: arigo Date: Thu Feb 26 13:55:21 2009 New Revision: 62178 Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py pypy/branch/pyjitpl5/pypy/rpython/rlist.py Log: Reorganize a bit the oopspec of list. Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rlist.py Thu Feb 26 13:55:21 2009 @@ -313,6 +313,7 @@ def ll_length(l): return l.length +ll_length.oopspec = 'list.len(l)' def ll_items(l): return l.items @@ -320,10 +321,12 @@ def ll_getitem_fast(l, index): ll_assert(index < l.length, "getitem out of bounds") return l.ll_items()[index] +ll_getitem_fast.oopspec = 'list.getitem(l, index)' def ll_setitem_fast(l, index, item): ll_assert(index < l.length, "setitem out of bounds") l.ll_items()[index] = item +ll_setitem_fast.oopspec = 'list.setitem(l, index, item)' # fixed size versions @@ -340,6 +343,7 @@ def ll_fixed_length(l): return len(l) +ll_fixed_length.oopspec = 'list.len(l)' def ll_fixed_items(l): return l @@ -347,10 +351,12 @@ def ll_fixed_getitem_fast(l, index): ll_assert(index < len(l), "fixed getitem out of bounds") return l[index] +ll_fixed_getitem_fast.oopspec = 'list.getitem(l, index)' def ll_fixed_setitem_fast(l, index, item): ll_assert(index < len(l), "fixed setitem out of bounds") l[index] = item +ll_fixed_setitem_fast.oopspec = 'list.setitem(l, index, item)' def newlist(llops, r_list, items_v): LIST = r_list.LIST Modified: pypy/branch/pyjitpl5/pypy/rpython/rlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rlist.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rlist.py Thu Feb 26 13:55:21 2009 @@ -517,28 +517,20 @@ new_lst.ll_setitem_fast(i, l.ll_getitem_fast(i)) i += 1 return new_lst -ll_copy.oopspec = 'list.copy(l)' def ll_len(l): return l.ll_length() -ll_len.oopspec = 'list.len(l)' -ll_len.oopargcheck = lambda l: bool(l) def ll_list_is_true(l): # check if a list is True, allowing for None return bool(l) and l.ll_length() != 0 -ll_list_is_true.oopspec = 'list.nonzero(l)' -ll_list_is_true.oopargcheck = lambda l: True def ll_len_foldable(l): return l.ll_length() ll_len_foldable.oopspec = 'list.len_foldable(l)' -ll_len_foldable.oopargcheck = lambda l: bool(l) def ll_list_is_true_foldable(l): - return ll_list_is_true(l) -ll_list_is_true_foldable.oopspec = 'list.nonzero_foldable(l)' -ll_list_is_true_foldable.oopargcheck = lambda l: True + return bool(l) and ll_len_foldable(l) != 0 def ll_append(l, newitem): length = l.ll_length() @@ -576,7 +568,6 @@ i += 1 j += 1 return l -ll_concat.oopspec = 'list.concat(l1, l2)' def ll_insert_nonneg(l, index, newitem): length = l.ll_length() @@ -663,7 +654,6 @@ l.ll_setitem_fast(length_1_i, tmp) i += 1 length_1_i -= 1 -ll_reverse.oopspec = 'list.reverse(l)' def ll_getitem_nonneg(func, l, index): ll_assert(index >= 0, "unexpectedly negative list getitem index") @@ -674,8 +664,6 @@ ll_assert(index < l.ll_length(), "list getitem index out of bound") return l.ll_getitem_fast(index) ll_getitem_nonneg.oopspec = 'list.getitem(l, index)' -ll_getitem_nonneg.oopargcheck = lambda l, index: (bool(l) and - 0 <= index < l.ll_length()) def ll_getitem(func, l, index): length = l.ll_length() @@ -689,21 +677,14 @@ ll_assert(index < length, "list getitem index out of bound") return l.ll_getitem_fast(index) ll_getitem.oopspec = 'list.getitem(l, index)' -ll_getitem.oopargcheck = lambda l, index: (bool(l) and -l.ll_length() <= - index < l.ll_length()) def ll_getitem_foldable_nonneg(func, l, index): return ll_getitem_nonneg(func, l, index) ll_getitem_foldable_nonneg.oopspec = 'list.getitem_foldable(l, index)' -ll_getitem_foldable_nonneg.oopargcheck = lambda l, index: (bool(l) and - 0 <= index < l.ll_length()) def ll_getitem_foldable(func, l, index): return ll_getitem(func, l, index) ll_getitem_foldable.oopspec = 'list.getitem_foldable(l, index)' -ll_getitem_foldable.oopargcheck = lambda l, index: (bool(l) - and -l.ll_length() <= - index < l.ll_length()) def ll_setitem_nonneg(func, l, index, newitem): ll_assert(index >= 0, "unexpectedly negative list setitem index") @@ -778,6 +759,7 @@ l1.ll_setitem_fast(j, l2.ll_getitem_fast(i)) i += 1 j += 1 +ll_extend.oopspec = 'list.extend(l1, l2)' def ll_extend_with_str(lst, s, getstrlen, getstritem): return ll_extend_with_str_slice_startonly(lst, s, getstrlen, getstritem, 0) From arigo at codespeak.net Thu Feb 26 13:56:11 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 13:56:11 +0100 (CET) Subject: [pypy-svn] r62179 - pypy/branch/pyjitpl5/pypy/interpreter Message-ID: <20090226125611.1414F1684D2@codespeak.net> Author: arigo Date: Thu Feb 26 13:56:10 2009 New Revision: 62179 Modified: pypy/branch/pyjitpl5/pypy/interpreter/baseobjspace.py pypy/branch/pyjitpl5/pypy/interpreter/gateway.py pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py pypy/branch/pyjitpl5/pypy/interpreter/pyopcode.py Log: Remove most hints in the Python interpreter. They are not useful any more. Modified: pypy/branch/pyjitpl5/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/baseobjspace.py Thu Feb 26 13:56:10 2009 @@ -4,7 +4,6 @@ from pypy.interpreter.argument import Arguments, ArgumentsFromValuestack from pypy.interpreter.pycompiler import CPythonCompiler, PythonAstCompiler from pypy.interpreter.miscutils import ThreadLocals -from pypy.rlib.jit import hint from pypy.tool.cache import Cache from pypy.tool.uid import HUGEVAL_BYTES from pypy.rlib.objectmodel import we_are_translated @@ -724,7 +723,6 @@ if not self.config.objspace.disable_call_speedhacks: # XXX start of hack for performance - hint(w_func.__class__, promote=True) if isinstance(w_func, Method): w_inst = w_func.w_instance if w_inst is not None: Modified: pypy/branch/pyjitpl5/pypy/interpreter/gateway.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/gateway.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/gateway.py Thu Feb 26 13:56:10 2009 @@ -20,7 +20,6 @@ from pypy.interpreter.baseobjspace import Wrappable, SpaceCache, DescrMismatch from pypy.interpreter.argument import Arguments, AbstractArguments from pypy.tool.sourcetools import NiceCompile, compile2 -from pypy.rlib.jit import hint from pypy.rlib.rarithmetic import r_longlong, r_int, r_ulonglong, r_uint # internal non-translatable parts: @@ -572,7 +571,7 @@ fast_natural_arity = 0 def fastcall_0(self, space, w_func): - self = hint(self, deepfreeze=True) + #self = hint(self, deepfreeze=True) try: w_result = self.fastfunc_0(space) except KeyboardInterrupt: @@ -592,7 +591,7 @@ fast_natural_arity = 1 def fastcall_1(self, space, w_func, w1): - self = hint(self, deepfreeze=True) + #self = hint(self, deepfreeze=True) try: w_result = self.fastfunc_1(space, w1) except KeyboardInterrupt: @@ -617,7 +616,7 @@ fast_natural_arity = 2 def fastcall_2(self, space, w_func, w1, w2): - self = hint(self, deepfreeze=True) + #self = hint(self, deepfreeze=True) try: w_result = self.fastfunc_2(space, w1, w2) except KeyboardInterrupt: @@ -642,7 +641,7 @@ fast_natural_arity = 3 def fastcall_3(self, space, func, w1, w2, w3): - self = hint(self, deepfreeze=True) + #self = hint(self, deepfreeze=True) try: w_result = self.fastfunc_3(space, w1, w2, w3) except KeyboardInterrupt: @@ -667,7 +666,7 @@ fast_natural_arity = 4 def fastcall_4(self, space, func, w1, w2, w3, w4): - self = hint(self, deepfreeze=True) + #self = hint(self, deepfreeze=True) try: w_result = self.fastfunc_4(space, w1, w2, w3, w4) except KeyboardInterrupt: Modified: pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/pyframe.py Thu Feb 26 13:56:10 2009 @@ -46,7 +46,7 @@ is_being_profiled = False def __init__(self, space, code, w_globals, closure): - self = hint(self, access_directly=True) + #self = hint(self, access_directly=True) assert isinstance(code, pycode.PyCode) self.pycode = code eval.Frame.__init__(self, space, w_globals, code.co_nlocals) @@ -145,7 +145,6 @@ n -= 1 if n < 0: break - hint(n, concrete=True) w_value = self.popvalue() w_key = self.popvalue() key = self.space.str_w(w_key) @@ -161,7 +160,6 @@ n -= 1 if n < 0: break - hint(n, concrete=True) values_w[n] = self.popvalue() return values_w return popvalues @@ -177,7 +175,6 @@ n -= 1 if n < 0: break - hint(n, concrete=True) values_w[n] = self.valuestack_w[base+n] return values_w @@ -188,7 +185,6 @@ n -= 1 if n < 0: break - hint(n, concrete=True) self.valuestack_w[finaldepth+n] = None self.valuestackdepth = finaldepth @@ -197,7 +193,6 @@ n -= 1 if n < 0: break - hint(n, concrete=True) self.pushvalue(values_w[n]) def dupvalues(self, n): @@ -206,7 +201,6 @@ n -= 1 if n < 0: break - hint(n, concrete=True) w_value = self.peekvalue(delta) self.pushvalue(w_value) @@ -361,7 +355,7 @@ return self.pycode.hidden_applevel def getcode(self): - return hint(hint(self.pycode, promote=True), deepfreeze=True) + return hint(self.pycode, promote=True) def getfastscope(self): "Get the fast locals as a list." Modified: pypy/branch/pyjitpl5/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/pyopcode.py Thu Feb 26 13:56:10 2009 @@ -183,8 +183,6 @@ oparg = (hi << 8) | lo else: oparg = 0 - hint(opcode, concrete=True) - hint(oparg, concrete=True) while opcode == opcodedesc.EXTENDED_ARG.index: opcode = ord(co_code[next_instr]) @@ -194,8 +192,6 @@ hi = ord(co_code[next_instr+2]) next_instr += 3 oparg = (oparg << 16) | (hi << 8) | lo - hint(opcode, concrete=True) - hint(oparg, concrete=True) if opcode == opcodedesc.RETURN_VALUE.index: w_returnvalue = self.popvalue() @@ -265,7 +261,6 @@ while n > 0: block = self.blockstack.pop() n -= 1 - hint(n, concrete=True) if (block.handling_mask & unroller_kind) != 0: return block block.cleanupstack(self) @@ -1128,7 +1123,7 @@ def handle(self, frame, unroller): next_instr = self.really_handle(frame, unroller) # JIT hack - return hint(next_instr, promote=True) + return next_instr def really_handle(self, frame, unroller): """ Purely abstract method From arigo at codespeak.net Thu Feb 26 13:56:40 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 13:56:40 +0100 (CET) Subject: [pypy-svn] r62180 - pypy/branch/pyjitpl5/pypy/module/pypyjit/test Message-ID: <20090226125640.9FF641684DC@codespeak.net> Author: arigo Date: Thu Feb 26 13:56:40 2009 New Revision: 62180 Removed: pypy/branch/pyjitpl5/pypy/module/pypyjit/test/test_newbool.py Log: Kill! Kill! (4th attempt) From cfbolz at codespeak.net Thu Feb 26 13:59:22 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 26 Feb 2009 13:59:22 +0100 (CET) Subject: [pypy-svn] r62181 - in pypy/branch/spy-graphic/pypy/lang/smalltalk: . test Message-ID: <20090226125922.22BF31684D2@codespeak.net> Author: cfbolz Date: Thu Feb 26 13:59:20 2009 New Revision: 62181 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py Log: Refactor way that bytecodes calling primitives directly are done. Speeds up translation a lot. Fix some small things. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/interpreter.py Thu Feb 26 13:59:20 2009 @@ -61,7 +61,7 @@ cnt = 0 p = self.w_active_context() # AK make method - while p is not self.space.w_nil: + while not p.is_same_object(self.space.w_nil): cnt += 1 # Do not update the context # for this action. @@ -94,6 +94,24 @@ def __init__(self, object): self.object = object +def make_call_primitive_bytecode(primitive, selector, argcount): + def callPrimitive(self, interp): + # WARNING: this is used for bytecodes for which it is safe to + # directly call the primitive. In general, it is not safe: for + # example, depending on the type of the receiver, bytecodePrimAt + # may invoke primitives.AT, primitives.STRING_AT, or anything + # else that the user put in a class in an 'at:' method. + # The rule of thumb is that primitives with only int and float + # in their unwrap_spec are safe. + func = primitives.prim_table[primitive] + try: + func(interp, argcount) + return + except primitives.PrimitiveFailedError: + pass + self._sendSelfSelector(selector, argcount, interp) + return callPrimitive + # ___________________________________________________________________________ # Bytecode Implementations: # @@ -222,7 +240,7 @@ def _return(self, object, interp, w_return_to): # for tests, when returning from the top-level context - if w_return_to is self.space.w_nil: + if w_return_to.is_same_object(self.space.w_nil): raise ReturnFromTopLevel(object) w_return_to.as_context_get_shadow(self.space).push(object) interp.store_w_active_context(w_return_to) @@ -371,93 +389,23 @@ def longJumpIfFalse(self, interp): self.jumpConditional(interp.space.w_false, self.longJumpPosition()) - # RPython trick: specialize the following function on its second argument - # this makes sure that the primitive call is a direct one - @objectmodel.specialize.arg(1) - def callPrimitive(self, primitive, selector, argcount, interp): - # WARNING: this is used for bytecodes for which it is safe to - # directly call the primitive. In general, it is not safe: for - # example, depending on the type of the receiver, bytecodePrimAt - # may invoke primitives.AT, primitives.STRING_AT, or anything - # else that the user put in a class in an 'at:' method. - # The rule of thumb is that primitives with only int and float - # in their unwrap_spec are safe. - for i, func in primitives.unrolling_prim_table: - if i == primitive: - try: - func(interp, argcount) - return - except primitives.PrimitiveFailedError: - break - self._sendSelfSelector(selector, argcount, interp) - - def callPrimitive2(self, primitive1, primitive2, - selector, argcount, interp): - # same as callPrimitive(), but tries two primitives before falling - # back to the general case. - try: - primitives.prim_table[primitive1](interp, argcount) - # the primitive pushes the result (if any) onto the stack itself - except primitives.PrimitiveFailedError: - self.callPrimitive(primitive2, selector, argcount, interp) - - def bytecodePrimAdd(self, interp): - self.callPrimitive(primitives.ADD, - "+", 1, interp) - - def bytecodePrimSubtract(self, interp): - self.callPrimitive(primitives.SUBTRACT, - "-", 1, interp) - - def bytecodePrimLessThan(self, interp): - self.callPrimitive(primitives.LESSTHAN, - "<", 1, interp) - - def bytecodePrimGreaterThan(self, interp): - self.callPrimitive(primitives.GREATERTHAN, - ">", 1, interp) - - def bytecodePrimLessOrEqual(self, interp): - self.callPrimitive(primitives.LESSOREQUAL, - "<=", 1, interp) - def bytecodePrimGreaterOrEqual(self, interp): - self.callPrimitive(primitives.GREATEROREQUAL, - ">=", 1, interp) - - def bytecodePrimEqual(self, interp): - self.callPrimitive(primitives.EQUAL, - "=", 1, interp) - - def bytecodePrimNotEqual(self, interp): - self.callPrimitive(primitives.NOTEQUAL, - "~=", 1, interp) - - def bytecodePrimMultiply(self, interp): - self.callPrimitive(primitives.MULTIPLY, - "*", 1, interp) - - def bytecodePrimDivide(self, interp): - self.callPrimitive(primitives.DIVIDE, - "/", 1, interp) - - def bytecodePrimMod(self, interp): - self.callPrimitive(primitives.MOD, "\\\\", 1, interp) - - def bytecodePrimMakePoint(self, interp): - self.callPrimitive(primitives.MAKE_POINT, "@", 1, interp) - - def bytecodePrimBitShift(self, interp): - self.callPrimitive(primitives.BIT_SHIFT, "bitShift:", 1, interp) - - def bytecodePrimDiv(self, interp): - self.callPrimitive(primitives.DIV, "//", 1, interp) - - def bytecodePrimBitAnd(self, interp): - self.callPrimitive(primitives.BIT_AND, "bitAnd:", 1, interp) - - def bytecodePrimBitOr(self, interp): - self.callPrimitive(primitives.BIT_OR, "bitOr:", 1, interp) + bytecodePrimAdd = make_call_primitive_bytecode(primitives.ADD, "+", 1) + bytecodePrimSubtract = make_call_primitive_bytecode(primitives.SUBTRACT, "-", 1) + bytecodePrimLessThan = make_call_primitive_bytecode (primitives.LESSTHAN, "<", 1) + bytecodePrimGreaterThan = make_call_primitive_bytecode(primitives.GREATERTHAN, ">", 1) + bytecodePrimLessOrEqual = make_call_primitive_bytecode(primitives.LESSOREQUAL, "<=", 1) + bytecodePrimGreaterOrEqual = make_call_primitive_bytecode(primitives.GREATEROREQUAL, ">=", 1) + bytecodePrimEqual = make_call_primitive_bytecode(primitives.EQUAL, "=", 1) + bytecodePrimNotEqual = make_call_primitive_bytecode(primitives.NOTEQUAL, "~=", 1) + bytecodePrimMultiply = make_call_primitive_bytecode(primitives.MULTIPLY, "*", 1) + bytecodePrimDivide = make_call_primitive_bytecode(primitives.DIVIDE, "/", 1) + bytecodePrimMod = make_call_primitive_bytecode(primitives.MOD, "\\\\", 1) + bytecodePrimMakePoint = make_call_primitive_bytecode(primitives.MAKE_POINT, "@", 1) + bytecodePrimBitShift = make_call_primitive_bytecode(primitives.BIT_SHIFT, "bitShift:", 1) + bytecodePrimDiv = make_call_primitive_bytecode(primitives.DIV, "//", 1) + bytecodePrimBitAnd = make_call_primitive_bytecode(primitives.BIT_AND, "bitAnd:", 1) + bytecodePrimBitOr = make_call_primitive_bytecode(primitives.BIT_OR, "bitOr:", 1) def bytecodePrimAt(self, interp): # n.b.: depending on the type of the receiver, this may invoke @@ -491,24 +439,10 @@ # which cannot fail primitives.prim_table[primitives.CLASS](interp, 0) - def bytecodePrimBlockCopy(self, interp): - # the primitive checks the class of the receiver - self.callPrimitive(primitives.BLOCK_COPY, - "blockCopy:", 1, interp) - - def bytecodePrimValue(self, interp): - # the primitive checks the class of the receiver - self.callPrimitive( - primitives.VALUE, "value", 0, interp) - - def bytecodePrimValueWithArg(self, interp): - # the primitive checks the class of the receiver - # Note that the VALUE_WITH_ARGS takes an array of - # arguments but this bytecode is about the one-argument case. - # The VALUE is general enough to take any number of - # arguments from the stack, so it's the one we need to use here. - self.callPrimitive( - primitives.VALUE, "value:", 1, interp) + + bytecodePrimBlockCopy = make_call_primitive_bytecode(primitives.BLOCK_COPY, "blockCopy:", 1) + bytecodePrimValue = make_call_primitive_bytecode(primitives.VALUE, "value", 0) + bytecodePrimValueWithArg = make_call_primitive_bytecode(primitives.VALUE, "value:", 1) def bytecodePrimDo(self, interp): self._sendSelfSelector("do:", 1, interp) @@ -527,77 +461,77 @@ BYTECODE_RANGES = [ - ( 0, 15, ContextPartShadow.pushReceiverVariableBytecode), - ( 16, 31, ContextPartShadow.pushTemporaryVariableBytecode), - ( 32, 63, ContextPartShadow.pushLiteralConstantBytecode), - ( 64, 95, ContextPartShadow.pushLiteralVariableBytecode), - ( 96, 103, ContextPartShadow.storeAndPopReceiverVariableBytecode), - (104, 111, ContextPartShadow.storeAndPopTemporaryVariableBytecode), - (112, ContextPartShadow.pushReceiverBytecode), - (113, ContextPartShadow.pushConstantTrueBytecode), - (114, ContextPartShadow.pushConstantFalseBytecode), - (115, ContextPartShadow.pushConstantNilBytecode), - (116, ContextPartShadow.pushConstantMinusOneBytecode), - (117, ContextPartShadow.pushConstantZeroBytecode), - (118, ContextPartShadow.pushConstantOneBytecode), - (119, ContextPartShadow.pushConstantTwoBytecode), - (120, ContextPartShadow.returnReceiver), - (121, ContextPartShadow.returnTrue), - (122, ContextPartShadow.returnFalse), - (123, ContextPartShadow.returnNil), - (124, ContextPartShadow.returnTopFromMethod), - (125, ContextPartShadow.returnTopFromBlock), - (126, ContextPartShadow.unknownBytecode), - (127, ContextPartShadow.unknownBytecode), - (128, ContextPartShadow.extendedPushBytecode), - (129, ContextPartShadow.extendedStoreBytecode), - (130, ContextPartShadow.extendedStoreAndPopBytecode), - (131, ContextPartShadow.singleExtendedSendBytecode), - (132, ContextPartShadow.doubleExtendedDoAnythingBytecode), - (133, ContextPartShadow.singleExtendedSuperBytecode), - (134, ContextPartShadow.secondExtendedSendBytecode), - (135, ContextPartShadow.popStackBytecode), - (136, ContextPartShadow.duplicateTopBytecode), - (137, ContextPartShadow.pushActiveContextBytecode), - (138, 143, ContextPartShadow.experimentalBytecode), - (144, 151, ContextPartShadow.shortUnconditionalJump), - (152, 159, ContextPartShadow.shortConditionalJump), - (160, 167, ContextPartShadow.longUnconditionalJump), - (168, 171, ContextPartShadow.longJumpIfTrue), - (172, 175, ContextPartShadow.longJumpIfFalse), - (176, ContextPartShadow.bytecodePrimAdd), - (177, ContextPartShadow.bytecodePrimSubtract), - (178, ContextPartShadow.bytecodePrimLessThan), - (179, ContextPartShadow.bytecodePrimGreaterThan), - (180, ContextPartShadow.bytecodePrimLessOrEqual), - (181, ContextPartShadow.bytecodePrimGreaterOrEqual), - (182, ContextPartShadow.bytecodePrimEqual), - (183, ContextPartShadow.bytecodePrimNotEqual), - (184, ContextPartShadow.bytecodePrimMultiply), - (185, ContextPartShadow.bytecodePrimDivide), - (186, ContextPartShadow.bytecodePrimMod), - (187, ContextPartShadow.bytecodePrimMakePoint), - (188, ContextPartShadow.bytecodePrimBitShift), - (189, ContextPartShadow.bytecodePrimDiv), - (190, ContextPartShadow.bytecodePrimBitAnd), - (191, ContextPartShadow.bytecodePrimBitOr), - (192, ContextPartShadow.bytecodePrimAt), - (193, ContextPartShadow.bytecodePrimAtPut), - (194, ContextPartShadow.bytecodePrimSize), - (195, ContextPartShadow.bytecodePrimNext), - (196, ContextPartShadow.bytecodePrimNextPut), - (197, ContextPartShadow.bytecodePrimAtEnd), - (198, ContextPartShadow.bytecodePrimEquivalent), - (199, ContextPartShadow.bytecodePrimClass), - (200, ContextPartShadow.bytecodePrimBlockCopy), - (201, ContextPartShadow.bytecodePrimValue), - (202, ContextPartShadow.bytecodePrimValueWithArg), - (203, ContextPartShadow.bytecodePrimDo), - (204, ContextPartShadow.bytecodePrimNew), - (205, ContextPartShadow.bytecodePrimNewWithArg), - (206, ContextPartShadow.bytecodePrimPointX), - (207, ContextPartShadow.bytecodePrimPointY), - (208, 255, ContextPartShadow.sendLiteralSelectorBytecode), + ( 0, 15, "pushReceiverVariableBytecode"), + ( 16, 31, "pushTemporaryVariableBytecode"), + ( 32, 63, "pushLiteralConstantBytecode"), + ( 64, 95, "pushLiteralVariableBytecode"), + ( 96, 103, "storeAndPopReceiverVariableBytecode"), + (104, 111, "storeAndPopTemporaryVariableBytecode"), + (112, "pushReceiverBytecode"), + (113, "pushConstantTrueBytecode"), + (114, "pushConstantFalseBytecode"), + (115, "pushConstantNilBytecode"), + (116, "pushConstantMinusOneBytecode"), + (117, "pushConstantZeroBytecode"), + (118, "pushConstantOneBytecode"), + (119, "pushConstantTwoBytecode"), + (120, "returnReceiver"), + (121, "returnTrue"), + (122, "returnFalse"), + (123, "returnNil"), + (124, "returnTopFromMethod"), + (125, "returnTopFromBlock"), + (126, "unknownBytecode"), + (127, "unknownBytecode"), + (128, "extendedPushBytecode"), + (129, "extendedStoreBytecode"), + (130, "extendedStoreAndPopBytecode"), + (131, "singleExtendedSendBytecode"), + (132, "doubleExtendedDoAnythingBytecode"), + (133, "singleExtendedSuperBytecode"), + (134, "secondExtendedSendBytecode"), + (135, "popStackBytecode"), + (136, "duplicateTopBytecode"), + (137, "pushActiveContextBytecode"), + (138, 143, "experimentalBytecode"), + (144, 151, "shortUnconditionalJump"), + (152, 159, "shortConditionalJump"), + (160, 167, "longUnconditionalJump"), + (168, 171, "longJumpIfTrue"), + (172, 175, "longJumpIfFalse"), + (176, "bytecodePrimAdd"), + (177, "bytecodePrimSubtract"), + (178, "bytecodePrimLessThan"), + (179, "bytecodePrimGreaterThan"), + (180, "bytecodePrimLessOrEqual"), + (181, "bytecodePrimGreaterOrEqual"), + (182, "bytecodePrimEqual"), + (183, "bytecodePrimNotEqual"), + (184, "bytecodePrimMultiply"), + (185, "bytecodePrimDivide"), + (186, "bytecodePrimMod"), + (187, "bytecodePrimMakePoint"), + (188, "bytecodePrimBitShift"), + (189, "bytecodePrimDiv"), + (190, "bytecodePrimBitAnd"), + (191, "bytecodePrimBitOr"), + (192, "bytecodePrimAt"), + (193, "bytecodePrimAtPut"), + (194, "bytecodePrimSize"), + (195, "bytecodePrimNext"), + (196, "bytecodePrimNextPut"), + (197, "bytecodePrimAtEnd"), + (198, "bytecodePrimEquivalent"), + (199, "bytecodePrimClass"), + (200, "bytecodePrimBlockCopy"), + (201, "bytecodePrimValue"), + (202, "bytecodePrimValueWithArg"), + (203, "bytecodePrimDo"), + (204, "bytecodePrimNew"), + (205, "bytecodePrimNewWithArg"), + (206, "bytecodePrimPointX"), + (207, "bytecodePrimPointY"), + (208, 255, "sendLiteralSelectorBytecode"), ] @@ -609,7 +543,7 @@ else: positions = range(entry[0], entry[1]+1) for pos in positions: - result[pos] = entry[-1] + result[pos] = getattr(ContextPartShadow, entry[-1]) assert None not in result return result Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_interpreter.py Thu Feb 26 13:59:20 2009 @@ -18,7 +18,7 @@ return chr(opcode) return get_opcode_chr for entry in interpreter.BYTECODE_RANGES: - name = entry[-1].__name__ + name = entry[-1] if len(entry) == 2: # no range globals()[name] = chr(entry[0]) else: From arigo at codespeak.net Thu Feb 26 14:01:43 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 14:01:43 +0100 (CET) Subject: [pypy-svn] r62182 - in pypy/branch/pyjitpl5/pypy: jit/metainterp jit/tl rpython Message-ID: <20090226130143.181E716847B@codespeak.net> Author: arigo Date: Thu Feb 26 14:01:41 2009 New Revision: 62182 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py pypy/branch/pyjitpl5/pypy/rpython/rlist.py Log: Some more simplifications in the oopspecs. Also disable inlining in pypyjit.py, to prevent inlining from removing the oopspec functions. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Feb 26 14:01:41 2009 @@ -460,6 +460,7 @@ serialize_op_cast_int_to_char = serialize_op_same_as serialize_op_cast_char_to_int = serialize_op_same_as serialize_op_cast_bool_to_int = serialize_op_same_as + serialize_op_resume_point = serialize_op_same_as def serialize_op_char_eq(self, op): self.default_serialize_op(op, 'int_eq') Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 26 14:01:41 2009 @@ -235,7 +235,7 @@ self.execute(%r, [b1, b2], "int", True) ''' % (_opimpl, _opimpl)).compile() - for _opimpl in ['int_is_true', 'int_neg', + for _opimpl in ['int_is_true', 'int_neg', 'bool_not', ]: exec py.code.Source(''' @arguments("box") Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Thu Feb 26 14:01:41 2009 @@ -95,11 +95,16 @@ # coming from modules like pypy.rpython.rlist. The following # functions are fished from the globals() by setup_extra_builtin(). -def _ll_1_newlist(LIST): +def _ll_0_newlist(LIST): return LIST.ll_newlist(0) -def _ll_2_newlist(LIST, count): +def _ll_1_newlist(LIST, count): return LIST.ll_newlist(count) -_ll_3_newlist = rlist.ll_alloc_and_set +def _ll_2_newlist(LIST, count, item): + return rlist.ll_alloc_and_set(LIST, count, item) +_ll_0_newlist.need_result_type = True +_ll_1_newlist.need_result_type = True +_ll_2_newlist.need_result_type = True + def _ll_1_list_len(l): return l.ll_length() def _ll_2_list_getitem(l, index): @@ -110,16 +115,12 @@ return rlist.ll_pop_default(rlist.dum_checkidx, l) def _ll_2_list_pop(l, index): return rlist.ll_pop(rlist.dum_checkidx, l, index) -def _ll_1_list_copy(l): - return rlist.ll_copy(lltype.typeOf(l).TO, l) _ll_2_list_append = rlist.ll_append _ll_2_list_extend = rlist.ll_extend _ll_3_list_insert = rlist.ll_insert_nonneg -_ll_1_list_nonzero = rlist.ll_list_is_true _ll_2_list_getitem_foldable = _ll_2_list_getitem _ll_1_list_len_foldable = _ll_1_list_len -_ll_1_list_nonzero_foldable = _ll_1_list_nonzero _ll_2_dict_getitem = rdict.ll_dict_getitem _ll_3_dict_setitem = rdict.ll_dict_setitem @@ -193,12 +194,13 @@ args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if '.' not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res - bk = rtyper.annotator.bookkeeper - args_s.insert(0, annmodel.SomePBC([bk.getdesc(LIST_OR_DICT.TO)])) else: LIST_OR_DICT = ll_args[0] s_result = annmodel.lltype_to_annotation(ll_res) impl = setup_extra_builtin(oopspec_name, len(args_s)) + if getattr(impl, 'need_result_type', False): + bk = rtyper.annotator.bookkeeper + args_s.insert(0, annmodel.SomePBC([bk.getdesc(ll_res.TO)])) # mixlevelann = MixLevelHelperAnnotator(rtyper) c_func = mixlevelann.constfunc(impl, args_s, s_result) Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Thu Feb 26 14:01:41 2009 @@ -9,6 +9,7 @@ from pypy.config.pypyoption import get_pypy_config, set_pypy_opt_level config = get_pypy_config(translating=True) +config.translation.backendopt.inline_threshold = 0 set_opt_level(config, level='1') config.objspace.compiler = 'ast' config.objspace.nofaking = True Modified: pypy/branch/pyjitpl5/pypy/rpython/rlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/rlist.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/rlist.py Thu Feb 26 14:01:41 2009 @@ -987,7 +987,6 @@ def ll_listremove(lst, obj, eqfn): index = ll_listindex(lst, obj, eqfn) # raises ValueError if obj not in lst ll_delitem_nonneg(dum_nocheck, lst, index) -ll_listremove.oopspec = 'list.remove(obj)' def ll_inplace_mul(l, factor): length = l.ll_length() From cfbolz at codespeak.net Thu Feb 26 14:01:58 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 26 Feb 2009 14:01:58 +0100 (CET) Subject: [pypy-svn] r62183 - pypy/branch/spy-graphic/pypy/lang/smalltalk Message-ID: <20090226130158.293741684C3@codespeak.net> Author: cfbolz Date: Thu Feb 26 14:01:57 2009 New Revision: 62183 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/wrapper.py Log: some small fixes and comments Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/wrapper.py Thu Feb 26 14:01:57 2009 @@ -11,12 +11,14 @@ def read(self, index0): try: return self.w_self.fetch(self.space, index0) + # XXX Index error never raised after translation except IndexError: raise WrapperException("Unexpected instance layout. Too small") def write(self, index0, w_new): try: self.w_self.store(self.space, index0, w_new) + # XXX Index error never raised after translation except IndexError: raise WrapperException("Unexpected instance layout. Too small") @@ -51,12 +53,9 @@ class ProcessWrapper(LinkWrapper): suspended_context, store_suspended_context = make_getter_setter(1) + priority = make_int_getter(2) my_list, store_my_list = make_getter_setter(3) - def priority(self): - w_priority = self.read(2) - return self.space.unwrap_int(w_priority) - def put_to_sleep(self): sched = scheduler(self.space) priority = self.priority() @@ -90,7 +89,7 @@ def suspend(self, interp): if self.is_active_process(): - assert self.my_list() is interp.space.w_nil + assert self.my_list().is_same_object(interp.space.w_nil) w_process = scheduler(self.space).highest_priority_process() process = ProcessWrapper(self.space, w_process).activate(interp) else: @@ -103,7 +102,7 @@ last_link, store_last_link = make_getter_setter(1) def is_empty_list(self): - return self.first_link() is self.space.w_nil + return self.first_link().is_same_object(self.space.w_nil) def add_last_link(self, w_object): if self.is_empty_list(): @@ -125,7 +124,7 @@ return w_first def remove(self, w_link): - if self.first_link() is w_link: + if self.first_link().is_same_object(w_link): self.remove_first_link_of_list() return else: From arigo at codespeak.net Thu Feb 26 14:02:16 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 14:02:16 +0100 (CET) Subject: [pypy-svn] r62184 - pypy/branch/pyjitpl5/pypy/doc/jit Message-ID: <20090226130216.DEB231684C3@codespeak.net> Author: arigo Date: Thu Feb 26 14:02:16 2009 New Revision: 62184 Added: pypy/branch/pyjitpl5/pypy/doc/jit/pyjitpl5.txt (contents, props changed) Modified: pypy/branch/pyjitpl5/pypy/doc/jit/index.txt Log: Check this in, although it is empty so far. Modified: pypy/branch/pyjitpl5/pypy/doc/jit/index.txt ============================================================================== --- pypy/branch/pyjitpl5/pypy/doc/jit/index.txt (original) +++ pypy/branch/pyjitpl5/pypy/doc/jit/index.txt Thu Feb 26 14:02:16 2009 @@ -31,6 +31,8 @@ - Current work and prototype in Prolog (!): see `this blog post`__. +- `Draft notes`_ about the current work in PyPy (Feb 08). + *(work and documentation in progress!)* .. __: http://morepypy.blogspot.com/2008/06/hi-all-some-news-from-jit-front.html @@ -43,3 +45,4 @@ .. _Theory: theory.html .. _Rainbow: rainbow.html .. _Backends: backend.html +.. _`Draft notes`: pyjitpl5.html Added: pypy/branch/pyjitpl5/pypy/doc/jit/pyjitpl5.txt ============================================================================== --- (empty file) +++ pypy/branch/pyjitpl5/pypy/doc/jit/pyjitpl5.txt Thu Feb 26 14:02:16 2009 @@ -0,0 +1,4 @@ +======================================================================== + PyJitPl5 +======================================================================== + From cfbolz at codespeak.net Thu Feb 26 14:06:47 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 26 Feb 2009 14:06:47 +0100 (CET) Subject: [pypy-svn] r62185 - in pypy/branch/spy-graphic/pypy/lang/smalltalk: . test Message-ID: <20090226130647.77B961684DC@codespeak.net> Author: cfbolz Date: Thu Feb 26 14:06:46 2009 New Revision: 62185 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py pypy/branch/spy-graphic/pypy/lang/smalltalk/objspace.py pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_miniimage.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Log: A bug in become that was hiding a bug in the test of become. Took me ages to find. Squeak is extreeeeeeeeeeeeemely strange, try the following and print it: #(1 2 3) at: 1 put: 5. #(1 2 3) Not what I would expect at all. Also implemented the clock primitive. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/model.py Thu Feb 26 14:06:46 2009 @@ -88,7 +88,10 @@ return self.getclass(space).as_class_get_shadow(space) def is_same_object(self, other): - """Compare object identity""" + """Compare object identity. This should be used instead of directly + using is everywhere in the interpreter, in case we ever want to + implement it differently (which is useful e.g. for proxies). Also, + SmallIntegers and Floats need a different implementation.""" return self is other def become(self, other): @@ -105,7 +108,6 @@ self.value = value def getclass(self, space): - """Return SmallInteger from special objects array.""" return space.w_SmallInteger def gethash(self): @@ -191,11 +193,8 @@ def invariant(self): return isinstance(self.hash, int) - def become(self, w_other): - if not isinstance(w_other, W_AbstractObjectWithIdentityHash): - return False + def _become(self, w_other): self.hash, w_other.hash = w_other.hash, self.hash - return True class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash): """Objects with arbitrary class (ie not CompiledMethod, SmallInteger or @@ -226,11 +225,9 @@ return (W_AbstractObjectWithIdentityHash.invariant(self) and isinstance(self.w_class, W_PointersObject)) - def become(self, w_other): - if not isinstance(w_other, W_AbstractObjectWithClassReference): - return False + def _become(self, w_other): self.w_class, w_other.w_class = w_other.w_class, self.w_class - return W_AbstractObjectWithIdentityHash.become(self, w_other) + W_AbstractObjectWithIdentityHash._become(self, w_other) class W_PointersObject(W_AbstractObjectWithClassReference): @@ -344,7 +341,8 @@ return False self._vars, w_other._vars = w_other._vars, self._vars self._shadow, w_other._shadow = w_other._shadow, self._shadow - return W_AbstractObjectWithClassReference.become(self, w_other) + W_AbstractObjectWithClassReference._become(self, w_other) + return True class W_BytesObject(W_AbstractObjectWithClassReference): @@ -386,6 +384,7 @@ return True def is_same_object(self, other): + # XXX this sounds very wrong to me if not isinstance(other, W_BytesObject): return False return self.bytes == other.bytes @@ -397,13 +396,7 @@ def at0(self, space, index0): val = self.getword(index0) - if val & (3 << 30) == 0: - return space.wrap_int(val) - else: - w_result = W_BytesObject(space.classtable['w_LargePositiveInteger'], 4) - for i in range(4): - w_result.setchar(i, chr((val >> i*8) & 255)) - return w_result + return space.wrap_pos_full_int(val) def atput0(self, space, index0, w_value): if isinstance(w_value, W_BytesObject): @@ -459,6 +452,21 @@ self.setheader(header) self.bytes = "\x00"*bytecount + def become(self, w_other): + if not isinstance(w_other, W_CompiledMethod): + return False + self.argsize, w_other.argsize = w_other.argsize, self.argsize + self.primitive, w_other.primitive = w_other.primitive, self.primitive + self.literals, w_other.literals = w_other.literals, self.literals + self.tempsize, w_other.tempsize = w_other.tempsize, self.tempsize + self.bytes, w_other.bytes = w_other.bytes, self.bytes + self.header, w_other.header = w_other.header, self.header + self.literalsize, w_other.literalsize = w_other.literalsize, self.literalsize + self.w_compiledin, w_other.w_compiledin = w_other.w_compiledin, self.w_compiledin + self.islarge, w_other.islarge = w_other.islarge, self.islarge + W_AbstractObjectWithIdentityHash._become(self, w_other) + return True + def compiledin(self): if self.w_compiledin is None: from pypy.lang.smalltalk import wrapper Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/objspace.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/objspace.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/objspace.py Thu Feb 26 14:06:46 2009 @@ -163,6 +163,19 @@ return model.W_SmallInteger(val) raise WrappingError("integer too large to fit into a tagged pointer") + def wrap_pos_full_int(self, val): + if val < 0: + raise WrappingError("negative integer") + try: + return self.wrap_int(val) + except WrappingError: + pass + # XXX this is not really working well on 64 bit machines + w_result = model.W_BytesObject(self.classtable['w_LargePositiveInteger'], 4) + for i in range(4): + w_result.setchar(i, chr((val >> i*8) & 255)) + return w_result + def wrap_float(self, i): return model.W_Float(i) @@ -216,6 +229,8 @@ elif isinstance(w_v, model.W_SmallInteger): return float(w_v.value) raise UnwrappingError() + def _freeze_(self): + return True def bootstrap_class(space, instsize, w_superclass=None, w_metaclass=None, Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Thu Feb 26 14:06:46 2009 @@ -595,8 +595,9 @@ @expose_primitive(SECONDS_CLOCK, unwrap_spec=[object]) def func(interp, w_arg): import time - return interp.space.wrap_int(0x23910d6c) # HACK: too big for a small int! - #return interp.space.wrap_int(int(time.time())) + sec_since_epoch = int(time.time()) + sec_since_1901 = sec_since_epoch + ((69 * 365 + 17) * 24 * 3600) + return interp.space.wrap_pos_full_int(sec_since_1901) # ___________________________________________________________________________ # Boolean Primitives @@ -796,7 +797,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.classtable['w_Semaphore']): + interp.space.w_Semaphore): raise PrimitiveFailedError() wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(interp) return w_rcvr @@ -805,7 +806,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.classtable['w_Semaphore']): + interp.space.w_Semaphore): raise PrimitiveFailedError() wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(interp) return w_rcvr @@ -814,7 +815,7 @@ def func(interp, w_rcvr,): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.classtable['w_Process']): + interp.space.w_Process): raise PrimitiveFailedError() wrapper.ProcessWrapper(interp.space, w_rcvr).resume(interp) return w_rcvr @@ -823,7 +824,7 @@ def func(interp, w_rcvr): # XXX we might want to disable this check if not w_rcvr.getclass(interp.space).is_same_object( - interp.space.classtable['w_Process']): + interp.space.w_Process): raise PrimitiveFailedError() wrapper.ProcessWrapper(interp.space, w_rcvr).suspend(interp) return w_rcvr Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_miniimage.py Thu Feb 26 14:06:46 2009 @@ -261,23 +261,24 @@ p1 := 1 at 2. p2 := #(3 4 5). a := p1 -> p2. - (1 at 2 = a key) ifFalse: [^false]. - (#(3 4 5) = a value) ifFalse: [^false]. - (p1 -> p2 = a) ifFalse: [^false]. - (p1 == a key) ifFalse: [^false]. - (p2 == a value) ifFalse: [^false]. + (1 at 2 = a key) ifFalse: [^1]. + (#(3 4 5) = a value) ifFalse: [^2]. + (p1 -> p2 = a) ifFalse: [^3]. + (p1 == a key) ifFalse: [^4]. + (p2 == a value) ifFalse: [^5]. p1 become: p2. - (1 at 2 = a value) ifFalse: [^false]. - (#(3 4 5) = a key) ifFalse: [^false]. - (p1 -> p2 = a) ifFalse: [^false]. - (p1 == a key) ifFalse: [^false]. - (p2 == a value) ifFalse: [^false]. + (1 at 2 = a value) ifFalse: [^6]. + (3 = (a key at: 1)) ifFalse: [^7]. + (4 = (a key at: 2)) ifFalse: [^8]. + (5 = (a key at: 3)) ifFalse: [^9]. + (p1 -> p2 = a) ifFalse: [^10]. + (p1 == a key) ifFalse: [^11]. + (p2 == a value) ifFalse: [^12]. - ^true""" + ^42""" perform(w(10).getclass(space), "compile:classified:notifying:", w(sourcecode), w('pypy'), w(None)) - w_true = w(True) w_result = perform(w(10), "testBecome") - w_result.is_same_object(w_true) + assert space.unwrap_int(w_result) == 42 def perform(w_receiver, selector, *arguments_w): interp = interpreter.Interpreter(space) Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Thu Feb 26 14:06:46 2009 @@ -46,11 +46,9 @@ def prim_fails(code, stack): interp, argument_count = mock(stack) orig_stack = list(interp.s_active_context().stack()) - try: - prim_table[code](interp, argument_count-1) - py.test.fail("Expected PrimitiveFailedError") - except PrimitiveFailedError: - assert interp.s_active_context().stack() == orig_stack + py.test.raises(PrimitiveFailedError, + "prim_table[code](interp, argument_count - 1)") + assert interp.s_active_context().stack() == orig_stack # smallinteger tests def test_small_int_add(): @@ -291,9 +289,9 @@ assert prim(primitives.CLASS, [1]).is_same_object(space.w_SmallInteger) def test_as_oop(): - py.test.skip("not yet clear what AS_OOP returns: hash or header?") + # I checked potato, and that returns the hash for as_oop w_obj = mockclass(space, 0).as_class_get_shadow(space).new() - w_obj.w_hash = wrap(22) + w_obj.hash = 22 assert prim(primitives.AS_OOP, [w_obj]).value == 22 def test_as_oop_not_applicable_to_int(): @@ -396,7 +394,13 @@ def test_seconds_clock(): import time now = int(time.time()) - assert (prim(primitives.SECONDS_CLOCK, [42]).value - now) <= 2 + w_smalltalk_now1 = prim(primitives.SECONDS_CLOCK, [42]) + assert (now % 256 - ord(w_smalltalk_now1.bytes[0])) % 256 <= 2 + w_smalltalk_now2 = prim(primitives.SECONDS_CLOCK, [42]) + # the high-order byte should only change by one (and even that is + # extreeemely unlikely) + assert (ord(w_smalltalk_now2.bytes[-1]) - ord(w_smalltalk_now1.bytes[-1])) <= 1 + def test_load_inst_var(): " try to test the LoadInstVar primitives a little " From cfbolz at codespeak.net Thu Feb 26 14:13:27 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 26 Feb 2009 14:13:27 +0100 (CET) Subject: [pypy-svn] r62186 - pypy/branch/io-lang Message-ID: <20090226131327.A18E31684D2@codespeak.net> Author: cfbolz Date: Thu Feb 26 14:13:27 2009 New Revision: 62186 Added: pypy/branch/io-lang/ - copied from r62185, pypy/trunk/ Log: Make a branch for David to experiment with the IO language in. Was that an English sentence? From david at codespeak.net Thu Feb 26 16:00:44 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 26 Feb 2009 16:00:44 +0100 (CET) Subject: [pypy-svn] r62189 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090226150044.B0EEB168466@codespeak.net> Author: david Date: Thu Feb 26 16:00:42 2009 New Revision: 62189 Added: pypy/branch/io-lang/pypy/lang/io/ pypy/branch/io-lang/pypy/lang/io/__init__.py pypy/branch/io-lang/pypy/lang/io/test/ pypy/branch/io-lang/pypy/lang/io/test/__init__.py Log: Create directory structure Added: pypy/branch/io-lang/pypy/lang/io/__init__.py ============================================================================== Added: pypy/branch/io-lang/pypy/lang/io/test/__init__.py ============================================================================== From arigo at codespeak.net Thu Feb 26 16:04:34 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 16:04:34 +0100 (CET) Subject: [pypy-svn] r62190 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090226150434.C22E51684D2@codespeak.net> Author: arigo Date: Thu Feb 26 16:04:34 2009 New Revision: 62190 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Log: Add a few overflow-checking integer operations. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Feb 26 16:04:34 2009 @@ -59,6 +59,9 @@ 'int_ne' : (('int', 'int'), 'bool'), 'int_is_true' : (('int',), 'bool'), 'int_neg' : (('int',), 'int'), + 'int_add_ovf' : (('int', 'int'), 'int'), + 'int_sub_ovf' : (('int', 'int'), 'int'), + 'int_mul_ovf' : (('int', 'int'), 'int'), 'bool_not' : (('bool',), 'bool'), 'new_with_vtable' : (('int', 'ptr'), 'ptr'), 'new' : (('int',), 'ptr'), @@ -802,17 +805,19 @@ items[i] = default_val return res - def op_cast_int_to_ptr(self, i): - if i == 0: - return dummy_null - elif i == 1: - return dummy_nonnull - else: - raise Exception("cast_int_to_ptr: got %d" % (i,)) - -DUMMY = lltype.GcStruct('DUMMY') -dummy_null = lltype.nullptr(DUMMY) -dummy_nonnull = lltype.malloc(DUMMY, immortal=True) + for _opname in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', + ]: + exec py.code.Source(''' + def op_%s(self, x, y): + try: + z = LLFrame.op_%s(self, x, y) + except LLException, e: + self.catch_exception(e) + z = 0 + else: + self.clear_exception() + return z + ''' % (_opname, _opname)).compile() # ____________________________________________________________ Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Feb 26 16:04:34 2009 @@ -471,6 +471,9 @@ serialize_op_unichar_eq = serialize_op_char_eq serialize_op_unichar_ne = serialize_op_char_ne + def serialize_op_int_add_nonneg_ovf(self, op): + self.default_serialize_op(op, 'int_add_ovf') + def serialize_op_hint(self, op): hints = op.args[1].value if hints.get('promote') and op.args[0].concretetype is not lltype.Void: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 26 16:04:34 2009 @@ -235,6 +235,14 @@ self.execute(%r, [b1, b2], "int", True) ''' % (_opimpl, _opimpl)).compile() + for _opimpl in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', + ]: + exec py.code.Source(''' + @arguments("box", "box") + def opimpl_%s(self, b1, b2): + return self.execute_with_exc(%r, [b1, b2], "int", True) + ''' % (_opimpl, _opimpl)).compile() + for _opimpl in ['int_is_true', 'int_neg', 'bool_not', ]: exec py.code.Source(''' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Thu Feb 26 16:04:34 2009 @@ -1,6 +1,7 @@ import py from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rlib.jit import JitDriver, hint +from pypy.rlib.rarithmetic import ovfcheck from pypy.jit.metainterp.policy import StopAtXPolicy @@ -294,6 +295,20 @@ res = self.meta_interp(main, [13], policy=StopAtXPolicy(check)) assert res == 132 + def test_int_ovf(self): + myjitdriver = JitDriver(greens = [], reds = ['n']) + def f(n): + try: + while 1: + myjitdriver.can_enter_jit(n=n) + myjitdriver.jit_merge_point(n=n) + n = ovfcheck(n * -3) + except OverflowError: + return n + expected = f(1) + res = self.meta_interp(f, [1]) + assert res == expected + class MyError(Exception): def __init__(self, n): From arigo at codespeak.net Thu Feb 26 16:18:30 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 16:18:30 +0100 (CET) Subject: [pypy-svn] r62191 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090226151830.B587A1684FD@codespeak.net> Author: arigo Date: Thu Feb 26 16:18:30 2009 New Revision: 62191 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Log: Add caching to avoid repeated construction of the MixLevelHelperAnnotator. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Thu Feb 26 16:18:30 2009 @@ -191,6 +191,11 @@ raise ValueError(op.opname) def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res): + key = (oopspec_name, tuple(ll_args), ll_res) + try: + return rtyper._builtin_func_for_spec_cache[key] + except (KeyError, AttributeError): + pass args_s = [annmodel.lltype_to_annotation(v) for v in ll_args] if '.' not in oopspec_name: # 'newxxx' operations LIST_OR_DICT = ll_res @@ -206,4 +211,8 @@ c_func = mixlevelann.constfunc(impl, args_s, s_result) mixlevelann.finish() # + if not hasattr(rtyper, '_builtin_func_for_spec_cache'): + rtyper._builtin_func_for_spec_cache = {} + rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT) + # return c_func, LIST_OR_DICT From david at codespeak.net Thu Feb 26 17:34:35 2009 From: david at codespeak.net (david at codespeak.net) Date: Thu, 26 Feb 2009 17:34:35 +0100 (CET) Subject: [pypy-svn] r62195 - in pypy/branch/io-lang/pypy/lang/io: . test Message-ID: <20090226163435.D0F0B1684FD@codespeak.net> Author: david Date: Thu Feb 26 17:34:35 2009 New Revision: 62195 Added: pypy/branch/io-lang/pypy/lang/io/parserhack.io pypy/branch/io-lang/pypy/lang/io/parserhack.py pypy/branch/io-lang/pypy/lang/io/test/test_parse.py Log: (cfbolz, david) small hack to use io interpreter to parse code Added: pypy/branch/io-lang/pypy/lang/io/parserhack.io ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/parserhack.io Thu Feb 26 17:34:35 2009 @@ -0,0 +1,29 @@ +nil addAst := nil +nil addTail := nil +Message addAst := method( + "Ast(" print + next addAst +) +Message pythonize := method( + addAst + "implicit" print + addTail +) +Message addTail := method( + ", \"" print + name print + "\"" print + ", [" print + arguments foreach(i, argument, argument pythonize; ", " print) + "])" print + next addTail +) + +in := File standardInput +lines := in readLines +in close +all := "" asMutable +lines foreach(i, line, all appendSeq(line, "\n")) + +ms := Compiler messageForString(all) +ms pythonize \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/parserhack.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/parserhack.py Thu Feb 26 17:34:35 2009 @@ -0,0 +1,32 @@ +import py +import os + +implicit = "implicit" + +io_file = py.magic.autopath().dirpath().join("parserhack.io") + +class Ast(object): + def __init__(self, receiver, name, arguments = None): + self.receiver = receiver + self.name = name + if arguments is None: + arguments = [] + self.arguments = arguments + + def __repr__(self): + return "Ast(%r, %r, %r)" % (self.receiver, self.name, self.arguments) + + def __eq__(self, other): + return (self.__class__ is other.__class__ and + self.__dict__ == other.__dict__) + + def __ne__(self, other): + return not self == other + +def parse(input): + child_in, child_out_err = os.popen4("osxvm %s" % io_file) + child_in.write(input) + child_in.close() + s = child_out_err.read().strip() + return eval(s) + \ No newline at end of file Added: pypy/branch/io-lang/pypy/lang/io/test/test_parse.py ============================================================================== --- (empty file) +++ pypy/branch/io-lang/pypy/lang/io/test/test_parse.py Thu Feb 26 17:34:35 2009 @@ -0,0 +1,12 @@ +from pypy.lang.io.parserhack import parse, implicit, Ast + +def test_simple(): + input = "a b c" + ast = parse(input) + assert ast == Ast(Ast(Ast(implicit, "a"), "b"), "c") + +def test_simple_args(): + input = "a + b c" + ast = parse(input) + assert ast == Ast(Ast(implicit, "a"), '+', [Ast(Ast(implicit, 'b'), 'c')]) + From arigo at codespeak.net Thu Feb 26 18:45:41 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 18:45:41 +0100 (CET) Subject: [pypy-svn] r62197 - in pypy/branch/pyjitpl5/pypy: jit/backend/llgraph jit/metainterp jit/metainterp/test jit/tl module/pypyjit rpython Message-ID: <20090226174541.30A2B1684D2@codespeak.net> Author: arigo Date: Thu Feb 26 18:45:40 2009 New Revision: 62197 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Log: - Some progress in translating PyPy. - Support for low-level ops of creating, reading and writing a GcArray. - Fixes of llinterp to let ExtendedLLFrame calls create non-ExtendedLLFrames. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Thu Feb 26 18:45:40 2009 @@ -65,6 +65,7 @@ 'bool_not' : (('bool',), 'bool'), 'new_with_vtable' : (('int', 'ptr'), 'ptr'), 'new' : (('int',), 'ptr'), + 'new_array' : (('int', 'int'), 'ptr'), 'oononnull' : (('ptr',), 'bool'), 'ooisnull' : (('ptr',), 'bool'), 'oois' : (('ptr', 'ptr'), 'bool'), @@ -73,6 +74,8 @@ 'getfield_gc' : (('ptr', 'fieldname'), 'intorptr'), 'setfield_raw' : (('ptr', 'fieldname', 'intorptr'), None), 'getfield_raw' : (('ptr', 'fieldname'), 'intorptr'), + 'setarrayitem_gc' : (('ptr', 'int', 'int', 'intorptr'), None), + 'getarrayitem_gc' : (('ptr', 'int', 'int'), 'intorptr'), 'call_ptr' : (('ptr', 'varargs'), 'ptr'), 'call__4' : (('ptr', 'varargs'), 'int'), 'call_void' : (('ptr', 'varargs'), None), @@ -558,6 +561,11 @@ class ExtendedLLFrame(LLFrame): + def newsubframe(self, graph, args): + # the default implementation would also create an ExtendedLLFrame, + # but we don't want this to occur in our case + return LLFrame(graph, args, self.llinterpreter) + def op_return(self, value=None): if self.last_exception is None: raise ExecutionReturned(value) @@ -668,6 +676,10 @@ self.op_setfield_gc(ptr, 2, vtable) return ptr + def op_new_array(self, arraydesc, count): + ITEMTYPE = symbolic.Size2Type[arraydesc/2] + return lltype.malloc(lltype.GcArray(ITEMTYPE), count) + def op_getfield_gc(self, ptr, fielddesc): STRUCT, fieldname = symbolic.TokenToField[fielddesc/2] ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) @@ -679,22 +691,26 @@ lltype.Ptr(STRUCT)) return getattr(ptr, fieldname) + def _cast_newvalue(self, desc, TYPE, newvalue): + if desc % 2: + newvalue = lltype.cast_opaque_ptr(TYPE, newvalue) + else: + if isinstance(TYPE, lltype.Ptr): + assert TYPE.TO._gckind == 'raw' + newvalue = llmemory.cast_adr_to_ptr( + cast_int_to_adr(self.memocast, newvalue), + TYPE) + elif TYPE == llmemory.Address: + newvalue = cast_int_to_adr(self.memocast, newvalue) + return newvalue + def op_setfield_gc(self, ptr, fielddesc, newvalue): offset = fielddesc/2 STRUCT, fieldname = symbolic.TokenToField[offset] if lltype.typeOf(ptr) == llmemory.GCREF: ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), ptr) FIELDTYPE = getattr(STRUCT, fieldname) - if fielddesc % 2: - newvalue = lltype.cast_opaque_ptr(FIELDTYPE, newvalue) - else: - if isinstance(FIELDTYPE, lltype.Ptr): - assert FIELDTYPE.TO._gckind == 'raw' - newvalue = llmemory.cast_adr_to_ptr( - cast_int_to_adr(self.memocast, newvalue), - FIELDTYPE) - elif FIELDTYPE == llmemory.Address: - newvalue = cast_int_to_adr(self.memocast, newvalue) + newvalue = self._cast_newvalue(fielddesc, FIELDTYPE, newvalue) setattr(ptr, fieldname, newvalue) def op_setfield_raw(self, intval, fielddesc, newvalue): @@ -702,6 +718,16 @@ lltype.Ptr(STRUCT)) self.op_setfield_gc(ptr, fielddesc, newvalue) + def op_getarrayitem_gc(self, array, arraydesc, index): + array = array._obj.container + return array.getitem(index) + + def op_setarrayitem_gc(self, array, arraydesc, index, newvalue): + ITEMTYPE = symbolic.Size2Type[arraydesc/2] + array = array._obj.container + newvalue = self._cast_newvalue(arraydesc, ITEMTYPE, newvalue) + array.setitem(index, newvalue) + def op_ooisnull(self, ptr): if lltype.typeOf(ptr) != llmemory.GCREF: ptr = cast_int_to_adr(self.memocast, ptr) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Thu Feb 26 18:45:40 2009 @@ -253,6 +253,17 @@ return ofs*2 + bit @staticmethod + def arraydescrof(A): + assert isinstance(A, lltype.GcArray) + size = symbolic.get_size(A.OF) + token = history.getkind(A.OF) + if token == 'ptr': + bit = 1 + else: + bit = 0 + return size*2 + bit + + @staticmethod def typefor(fielddesc): if fielddesc % 2: return 'ptr' Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Feb 26 18:45:40 2009 @@ -214,6 +214,7 @@ self.portal = portal self.bytecode = self.codewriter.get_jitcode(graph) if not codewriter.policy.look_inside_graph(graph): + assert not portal, "portal has been hidden!" graph = make_calling_stub(codewriter.rtyper, graph) self.graph = graph @@ -499,17 +500,23 @@ # store the vtable as an address -- that's fine, because the # GC doesn't need to follow them self.emit('new_with_vtable', - self.cpu.sizeof(STRUCT), + self.const_position(self.cpu.sizeof(STRUCT)), self.const_position(vtable)) else: - self.emit('new', self.cpu.sizeof(STRUCT)) + self.emit('new', self.const_position(self.cpu.sizeof(STRUCT))) self.register_var(op.result) def serialize_op_malloc_varsize(self, op): - # XXX strings only for now - assert op.args[0].value == rstr.STR assert op.args[1].value == {'flavor': 'gc'} - self.emit('newstr', self.var_position(op.args[2])) + if op.args[0].value == rstr.STR: + self.emit('newstr', self.var_position(op.args[2])) + else: + # XXX only strings or simple arrays for now + ARRAY = op.args[0].value + arraydescr = self.cpu.arraydescrof(ARRAY) + self.emit('new_array') + self.emit(self.const_position(arraydescr)) + self.emit(self.var_position(op.args[2])) self.register_var(op.result) def serialize_op_zero_gc_pointers_inside(self, op): @@ -535,7 +542,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(offset) + self.emit(self.const_position(offset)) self.register_var(op.result) #self._eventualy_builtin(op.result) @@ -553,7 +560,7 @@ self.emit(self.var_position(v_inst)) offset = self.cpu.fielddescrof(v_inst.concretetype.TO, c_fieldname.value) - self.emit(offset) + self.emit(self.const_position(offset)) self.emit(self.var_position(v_value)) def is_typeptr_getset(self, op): @@ -566,6 +573,26 @@ self.emit('guard_class', self.var_position(op.args[0])) self.register_var(op.result) + def serialize_op_getarrayitem(self, op): + ARRAY = op.args[0].concretetype.TO + assert ARRAY._gckind == 'gc' + arraydescr = self.cpu.arraydescrof(ARRAY) + self.emit('getarrayitem_gc') + self.emit(self.var_position(op.args[0])) + self.emit(self.const_position(arraydescr)) + self.emit(self.var_position(op.args[1])) + self.register_var(op.result) + + def serialize_op_setarrayitem(self, op): + ARRAY = op.args[0].concretetype.TO + assert ARRAY._gckind == 'gc' + arraydescr = self.cpu.arraydescrof(ARRAY) + self.emit('setarrayitem_gc') + self.emit(self.var_position(op.args[0])) + self.emit(self.const_position(arraydescr)) + self.emit(self.var_position(op.args[1])) + self.emit(self.var_position(op.args[2])) + def serialize_op_getinteriorarraysize(self, op): # XXX only supports strings for now assert op.args[0].concretetype == lltype.Ptr(rstr.STR) @@ -725,7 +752,7 @@ self.emit('guard_nonvirtualized') self.emit(self.var_position(op.args[0])) self.emit(self.get_position(virtualizabledesc)) - self.emit(guard_field) + self.emit(self.const_position(guard_field)) # ---------- Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py Thu Feb 26 18:45:40 2009 @@ -2,6 +2,8 @@ class JitPolicy(object): def look_inside_function(self, func): + if hasattr(func, '_look_inside_me_'): + return func._look_inside_me_ # explicitly pure functions are always opaque if getattr(func, '_pure_function_', False): return False @@ -29,14 +31,13 @@ return None def guess_call_kind(self, op): - targetgraphs = self.graphs_from(op) - if targetgraphs is None: - return 'residual' - if len(targetgraphs) == 1: - [targetgraph] = targetgraphs + if op.opname == 'direct_call': + targetgraph = op.args[0].value._obj.graph if (hasattr(targetgraph, 'func') and hasattr(targetgraph.func, 'oopspec')): return 'builtin' + if self.graphs_from(op) is None: + return 'residual' return 'regular' @@ -48,3 +49,93 @@ if func in self.funcs: return False return super(StopAtXPolicy, self).look_inside_function(func) + +# ____________________________________________________________ + +from pypy.annotation.specialize import getuniquenondirectgraph + +class ManualJitPolicy(JitPolicy): + def __init__(self, translator): + self.translator = translator + self.bookkeeper = translator.annotator.bookkeeper + self.enabled_graphs = {} + self.fill_seen_graphs() + + def look_inside_graph(self, graph): + if self.enabled_graphs.get(graph): + return True + return super(ManualJitPolicy, self).look_inside_graph(graph) + + def fill_seen_graphs(self): + # subclasses should have their own + pass + + def _graph(self, func): + func = getattr(func, 'im_func', func) + desc = self.bookkeeper.getdesc(func) + return getuniquenondirectgraph(desc) + + def seefunc(self, fromfunc, *tofuncs): + targetgraphs = {} + for tofunc in tofuncs: + targetgraphs[self._graph(tofunc)] = True + graphs = graphs_on_the_path_to(self.translator, self._graph(fromfunc), + targetgraphs) + for graph in graphs: + if graph not in self.enabled_graphs: + self.enabled_graphs[graph] = True + print '++', graph + + def seepath(self, *path): + assert len(path) >= 2 + for i in range(1, len(path)): + self.seefunc(path[i-1], path[i]) + + def seegraph(self, func, look=True): + graph = self._graph(func) + self.enabled_graphs[graph] = look + if look: + print '++', graph + else: + print '--', graph + +def enumerate_reachable_graphs(translator, startgraph): + from pypy.translator.backendopt.support import find_calls_from + pending = [(startgraph, None)] + yield pending[0] + seen = {startgraph: True} + while pending: + yield None # hack: a separator meaning "length increases now" + nextlengthlist = [] + nextseen = {} + for node in pending: + head, tail = node + for block, callee in find_calls_from(translator, head): + if callee not in seen: + newnode = callee, node + yield newnode + nextlengthlist.append(newnode) + nextseen[callee] = True + pending = nextlengthlist + seen.update(nextseen) + yield None + +def graphs_on_the_path_to(translator, startgraph, targetgraphs): + targetgraphs = targetgraphs.copy() + result = {} + found = {} + for node in enumerate_reachable_graphs(translator, startgraph): + if node is None: # hack: a separator meaning "length increases now" + for graph in found: + del targetgraphs[graph] + found.clear() + if not targetgraphs: + return result + elif node[0] in targetgraphs: + found[node[0]] = True + while node is not None: + head, tail = node + result[head] = True + node = tail + raise Exception("did not reach all targets:\nmissing %r" % ( + targetgraphs.keys(),)) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 26 18:45:40 2009 @@ -293,13 +293,27 @@ self.pc = jumptargets[i] break - @arguments("int") - def opimpl_new(self, size): - self.execute('new', [ConstInt(size)], 'ptr') - - @arguments("int", "constbox") - def opimpl_new_with_vtable(self, size, vtableref): - self.execute('new_with_vtable', [ConstInt(size), vtableref], 'ptr') + @arguments("constbox") + def opimpl_new(self, sizebox): + self.execute('new', [sizebox], 'ptr') + + @arguments("constbox", "constbox") + def opimpl_new_with_vtable(self, sizebox, vtablebox): + self.execute('new_with_vtable', [sizebox, vtablebox], 'ptr') + + @arguments("constbox", "box") + def opimpl_new_array(self, itemsizebox, countbox): + self.execute('new_array', [itemsizebox, countbox], 'ptr') + + @arguments("box", "constbox", "box") + def opimpl_getarrayitem_gc(self, arraybox, arraydesc, indexbox): + tp = self.metainterp.cpu.typefor(arraydesc.getint()) + self.execute('getarrayitem_gc', [arraybox, arraydesc, indexbox], tp) + + @arguments("box", "constbox", "box", "box") + def opimpl_setarrayitem_gc(self, arraybox, arraydesc, indexbox, itembox): + self.execute('setarrayitem_gc', [arraybox, arraydesc, + indexbox, itembox], 'void') @arguments("box") def opimpl_ptr_nonzero(self, box): @@ -318,30 +332,30 @@ self.execute('ooisnot', [box1, box2], 'int', True) - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_gc(self, box, fielddesc): - tp = self.metainterp.cpu.typefor(fielddesc) - self.execute('getfield_gc', [box, ConstInt(fielddesc)], tp) - @arguments("box", "int") + tp = self.metainterp.cpu.typefor(fielddesc.getint()) + self.execute('getfield_gc', [box, fielddesc], tp) + @arguments("box", "constbox") def opimpl_getfield_pure_gc(self, box, fielddesc): - tp = self.metainterp.cpu.typefor(fielddesc) - self.execute('getfield_gc', [box, ConstInt(fielddesc)], tp, True) - @arguments("box", "int", "box") + tp = self.metainterp.cpu.typefor(fielddesc.getint()) + self.execute('getfield_gc', [box, fielddesc], tp, True) + @arguments("box", "constbox", "box") def opimpl_setfield_gc(self, box, fielddesc, valuebox): - self.execute('setfield_gc', [box, ConstInt(fielddesc), valuebox], + self.execute('setfield_gc', [box, fielddesc, valuebox], 'void') - @arguments("box", "int") + @arguments("box", "constbox") def opimpl_getfield_raw(self, box, fielddesc): - tp = self.metainterp.cpu.typefor(fielddesc) - self.execute('getfield_raw', [box, ConstInt(fielddesc)], tp) - @arguments("box", "int") + tp = self.metainterp.cpu.typefor(fielddesc.getint()) + self.execute('getfield_raw', [box, fielddesc], tp) + @arguments("box", "constbox") def opimpl_getfield_pure_raw(self, box, fielddesc): - tp = self.metainterp.cpu.typefor(fielddesc) - self.execute('getfield_raw', [box, ConstInt(fielddesc)], tp, True) - @arguments("box", "int", "box") + tp = self.metainterp.cpu.typefor(fielddesc.getint()) + self.execute('getfield_raw', [box, fielddesc], tp, True) + @arguments("box", "constbox", "box") def opimpl_setfield_raw(self, box, fielddesc, valuebox): - self.execute('setfield_raw', [box, ConstInt(fielddesc), valuebox], + self.execute('setfield_raw', [box, fielddesc, valuebox], 'void') @arguments("bytecode", "varargs") @@ -490,11 +504,11 @@ 'len', [builtin.len_func, box], 'int') self.generate_guard(pc, "guard_len", box, [intbox]) - @arguments("orgpc", "box", "virtualizabledesc", "int") + @arguments("orgpc", "box", "virtualizabledesc", "constbox") def opimpl_guard_nonvirtualized(self, pc, box, vdesc, guard_field): clsbox = self.cls_of_box(box) op = self.generate_guard(pc, 'guard_nonvirtualized', box, - [clsbox, ConstInt(guard_field)]) + [clsbox, guard_field]) if op: op.desc = vdesc Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Thu Feb 26 18:45:40 2009 @@ -217,6 +217,12 @@ res = self.meta_interp(f, [55]) assert res == -1 + def test_format(self): + def f(n): + return len("<%d>" % n) + res = self.interp_operations(f, [421]) + assert res == 5 + class TestOOtype(BasicTests, OOJitMixin): pass Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Thu Feb 26 18:45:40 2009 @@ -55,7 +55,10 @@ child_pid = os.fork() if child_pid == 0: break - os.waitpid(child_pid, 0) + try: + os.waitpid(child_pid, 0) + except KeyboardInterrupt: + pass print '-' * 79 print 'Child process finished, press Enter to restart...' raw_input() Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Thu Feb 26 18:45:40 2009 @@ -1,5 +1,6 @@ from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp import warmspot +from pypy.module.pypyjit.portal import PyPyJitPolicy def run_child(glob, loc): @@ -12,4 +13,5 @@ interp.heap.malloc_nonmovable = returns_null # XXX print 'warmspot.jittify_and_run() started...' - warmspot.jittify_and_run(interp, graph, []) + policy = PyPyJitPolicy(interp.typer.annotator.translator) + warmspot.jittify_and_run(interp, graph, [], policy=policy) Modified: pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py (original) +++ pypy/branch/pyjitpl5/pypy/module/pypyjit/portal.py Thu Feb 26 18:45:40 2009 @@ -1,25 +1,23 @@ import pypy -#from pypy.module.pypyjit.newbool import NewBoolDesc -from pypy.translator.translator import graphof -from pypy.annotation.specialize import getuniquenondirectgraph -from pypy.jit.hintannotator.policy import ManualGraphPolicy - -class PyPyHintAnnotatorPolicy(ManualGraphPolicy): - hotpath = True - - def look_inside_graph_of_module(self, graph, func, mod): - if mod.startswith('pypy.objspace'): +from pypy.jit.metainterp.policy import ManualJitPolicy + + +class PyPyJitPolicy(ManualJitPolicy): + + def look_inside_function(self, func): + mod = func.__module__ or '?' + if mod.startswith('pypy.objspace.'): return False if '_geninterp_' in func.func_globals: # skip all geninterped stuff return False - if mod.startswith('pypy.interpreter.astcompiler'): + if mod.startswith('pypy.interpreter.astcompiler.'): return False - if mod.startswith('pypy.interpreter.pyparser'): + if mod.startswith('pypy.interpreter.pyparser.'): return False if mod.startswith('pypy.module.'): if not mod.startswith('pypy.module.pypyjit.'): return False - if mod.startswith('pypy.translator.goal.nanos'): + if mod.startswith('pypy.translator.'): return False if mod in forbidden_modules: return False @@ -27,7 +25,7 @@ return False if func.__name__.startswith('fastfunc_'): return False - return True + return super(PyPyJitPolicy, self).look_inside_function(func) def seebinary(self, opname): name2 = name1 = opname[:3].lower() @@ -74,7 +72,7 @@ descr_impl, pypy.objspace.std.typeobject.W_TypeObject.is_heaptype) - def fill_timeshift_graphs(self): + def fill_seen_graphs(self): import pypy # -------------------- @@ -100,18 +98,16 @@ pypy.objspace.std.Space.is_w) self.seegraph(pypy.interpreter.pyframe.PyFrame.execute_frame, False) # -------------------- - # special timeshifting logic for newbool - #self.seegraph(pypy.objspace.std.Space.newbool, NewBoolDesc) self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_TRUE, pypy.objspace.std.Space.is_true) self.seepath(pypy.interpreter.pyframe.PyFrame.JUMP_IF_FALSE, pypy.objspace.std.Space.is_true) # - self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, - pypy.interpreter.function.Function.funccall_valuestack) - self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, - pypy.interpreter.function.Function.funccall_obj_valuestack) + #self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, + # pypy.interpreter.function.Function.funccall_valuestack) + #self.seepath(pypy.interpreter.pyframe.PyFrame.CALL_FUNCTION, + # pypy.interpreter.function.Function.funccall_obj_valuestack) Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py Thu Feb 26 18:45:40 2009 @@ -204,6 +204,9 @@ self.curr_operation_index = 0 self.alloca_objects = [] + def newsubframe(self, graph, args): + return self.__class__(graph, args, self.llinterpreter) + # _______________________________________________________ # variable setters/getters helpers @@ -662,7 +665,7 @@ if not lltype.isCompatibleType(T, v.concretetype): raise TypeError("graph with %r args called with wrong func ptr type: %r" % (tuple([v.concretetype for v in args_v]), ARGS)) - frame = self.__class__(graph, args, self.llinterpreter) + frame = self.newsubframe(graph, args) return frame.eval() def op_direct_call(self, f, *args): @@ -689,7 +692,7 @@ args = [] for inarg, arg in zip(inargs, obj.graph.startblock.inputargs): args.append(lltype._cast_whatever(arg.concretetype, inarg)) - frame = self.__class__(graph, args, self.llinterpreter) + frame = self.newsubframe(graph, args) result = frame.eval() from pypy.translator.stackless.frame import storage_type assert storage_type(lltype.typeOf(result)) == TGT From arigo at codespeak.net Thu Feb 26 19:05:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 26 Feb 2009 19:05:17 +0100 (CET) Subject: [pypy-svn] r62198 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090226180517.68DE61684F7@codespeak.net> Author: arigo Date: Thu Feb 26 19:05:15 2009 New Revision: 62198 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: Test and fix for switches: must encode the cases in boxes, because storing them directly into the bytecode crashes if there are negative values. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Thu Feb 26 19:05:15 2009 @@ -339,7 +339,8 @@ for link in switches] self.emit("switch", self.var_position(block.exitswitch)) - self.emit_list([link.llexitcase for link in switches]) + self.emit_list([self.const_position(link.llexitcase) + for link in switches]) self.emit_list([tlabel(link) for link in switches]) if block.exits[-1].exitcase == 'default': link = block.exits[-1] Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/dump.py Thu Feb 26 19:05:15 2009 @@ -56,9 +56,9 @@ count = self.load_int() return [self.load_arg() for i in range(count)] - def load_intargs(self): + def load_constargs(self): count = self.load_int() - return [self.load_int() for i in range(count)] + return [self.load_const_arg() for i in range(count)] def get_redarg(self): return CustomRepr('r%d' % self.load_int()) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Thu Feb 26 19:05:15 2009 @@ -61,8 +61,8 @@ args += (self.load_int(), ) elif argspec == "varargs": args += (self.load_varargs(), ) - elif argspec == "intargs": - args += (self.load_intargs(), ) + elif argspec == "constargs": + args += (self.load_constargs(), ) elif argspec == "bytecode": bytecode = self.load_const_arg() assert isinstance(bytecode, codewriter.JitCode) @@ -170,9 +170,9 @@ count = self.load_int() return [self.load_arg() for i in range(count)] - def load_intargs(self): + def load_constargs(self): count = self.load_int() - return [self.load_int() for i in range(count)] + return [self.load_const_arg() for i in range(count)] def getvarenv(self, i): return self.env[i] @@ -282,14 +282,13 @@ const_if_fail=const_if_fail) self.pc = currentpc - @arguments("orgpc", "box", "intargs", "jumptargets") - def opimpl_switch(self, pc, valuebox, intargs, jumptargets): + @arguments("orgpc", "box", "constargs", "jumptargets") + def opimpl_switch(self, pc, valuebox, constargs, jumptargets): box = self.implement_guard_value(pc, valuebox) - switchcase = box.getint() # XXX implement dictionary for speedups at some point - for i in range(len(intargs)): - value = intargs[i] - if switchcase == value: + for i in range(len(constargs)): + casebox = constargs[i] + if box.equals(casebox): self.pc = jumptargets[i] break Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Thu Feb 26 19:05:15 2009 @@ -223,6 +223,15 @@ res = self.interp_operations(f, [421]) assert res == 5 + def test_switch(self): + def f(n): + if n == -5: return 12 + elif n == 2: return 51 + elif n == 7: return 1212 + else: return 42 + res = self.interp_operations(f, [7]) + assert res == 1212 + class TestOOtype(BasicTests, OOJitMixin): pass From arigo at codespeak.net Fri Feb 27 09:32:15 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 09:32:15 +0100 (CET) Subject: [pypy-svn] r62201 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090227083215.A5B7F16851C@codespeak.net> Author: arigo Date: Fri Feb 27 09:32:13 2009 New Revision: 62201 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Log: Allow can_enter_jit to be placed outside the portal. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py Fri Feb 27 09:32:13 2009 @@ -110,6 +110,10 @@ llimpl.frame_add_int(frame, box.value) elif isinstance(box, history.BoxPtr): llimpl.frame_add_ptr(frame, box.value) + elif isinstance(box, history.ConstInt): + llimpl.frame_add_int(frame, box.value) + elif isinstance(box, history.ConstPtr): + llimpl.frame_add_ptr(frame, box.value) else: raise Exception("bad box in valueboxes: %r" % (box,)) return self.loop(frame) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Feb 27 09:32:13 2009 @@ -621,8 +621,8 @@ self.var_position(op.args[3])) def serialize_op_jit_marker(self, op): - assert self.portal, "jit_marker in non-main graph!" if op.args[0].value == 'jit_merge_point': + assert self.portal, "jit_merge_point in non-main graph!" self.emit('jit_merge_point') assert ([self.var_position(i) for i in op.args[2:]] == range(0, 2*(len(op.args) - 2), 2)) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_loop.py Fri Feb 27 09:32:13 2009 @@ -398,3 +398,24 @@ # XXX maybe later optimize guard_value away self.check_loops({'merge_point' : 1, 'int_add' : 6, 'int_gt' : 1, 'guard_false' : 1, 'jump' : 1, 'guard_value' : 3}) + + def test_can_enter_jit_outside_main_loop(self): + myjitdriver = JitDriver(greens=[], reds=['i', 'j', 'a']) + def done(a, j): + myjitdriver.can_enter_jit(i=0, j=j, a=a) + def main_interpreter_loop(a): + i = j = 0 + while True: + myjitdriver.jit_merge_point(i=i, j=j, a=a) + i += 1 + j += 3 + if i >= 10: + a -= 1 + if not a: + break + i = 0 + done(a, j) + return j + assert main_interpreter_loop(5) == 5 * 10 * 3 + res = self.meta_interp(main_interpreter_loop, [5]) + assert res == 5 * 10 * 3 From arigo at codespeak.net Fri Feb 27 09:33:59 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 09:33:59 +0100 (CET) Subject: [pypy-svn] r62202 - in pypy/branch/pyjitpl5/pypy: jit/backend/llgraph jit/metainterp rpython/lltypesystem translator/goal Message-ID: <20090227083359.D84C7168526@codespeak.net> Author: arigo Date: Fri Feb 27 09:33:59 2009 New Revision: 62202 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py pypy/branch/pyjitpl5/pypy/translator/goal/ann_override.py Log: Some more operations supported and some less hints in the source code of PyPy :-) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Feb 27 09:33:59 2009 @@ -59,9 +59,11 @@ 'int_ne' : (('int', 'int'), 'bool'), 'int_is_true' : (('int',), 'bool'), 'int_neg' : (('int',), 'int'), + 'int_invert' : (('int',), 'int'), 'int_add_ovf' : (('int', 'int'), 'int'), 'int_sub_ovf' : (('int', 'int'), 'int'), 'int_mul_ovf' : (('int', 'int'), 'int'), + 'int_neg_ovf' : (('int',), 'int'), 'bool_not' : (('bool',), 'bool'), 'new_with_vtable' : (('int', 'ptr'), 'ptr'), 'new' : (('int',), 'ptr'), @@ -832,11 +834,12 @@ return res for _opname in ['int_add_ovf', 'int_sub_ovf', 'int_mul_ovf', + 'int_neg_ovf', ]: exec py.code.Source(''' - def op_%s(self, x, y): + def op_%s(self, *args): try: - z = LLFrame.op_%s(self, x, y) + z = LLFrame.op_%s(self, *args) except LLException, e: self.catch_exception(e) z = 0 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Feb 27 09:33:59 2009 @@ -462,17 +462,26 @@ serialize_op_cast_int_to_char = serialize_op_same_as serialize_op_cast_char_to_int = serialize_op_same_as serialize_op_cast_bool_to_int = serialize_op_same_as + serialize_op_cast_int_to_uint = serialize_op_same_as + serialize_op_cast_uint_to_int = serialize_op_same_as serialize_op_resume_point = serialize_op_same_as - def serialize_op_char_eq(self, op): - self.default_serialize_op(op, 'int_eq') - - def serialize_op_char_ne(self, op): - self.default_serialize_op(op, 'int_ne') + _defl = default_serialize_op + def serialize_op_char_eq(self, op): self._defl(op, 'int_eq') + def serialize_op_char_ne(self, op): self._defl(op, 'int_ne') serialize_op_unichar_eq = serialize_op_char_eq serialize_op_unichar_ne = serialize_op_char_ne + def serialize_op_uint_add(self, op): self._defl(op, 'int_add') + def serialize_op_uint_sub(self, op): self._defl(op, 'int_sub') + def serialize_op_uint_lt (self, op): self._defl(op, 'int_lt') + def serialize_op_uint_le (self, op): self._defl(op, 'int_le') + def serialize_op_uint_eq (self, op): self._defl(op, 'int_eq') + def serialize_op_uint_ne (self, op): self._defl(op, 'int_ne') + def serialize_op_uint_gt (self, op): self._defl(op, 'int_gt') + def serialize_op_uint_ge (self, op): self._defl(op, 'int_ge') + def serialize_op_int_add_nonneg_ovf(self, op): self.default_serialize_op(op, 'int_add_ovf') @@ -483,7 +492,8 @@ self.emit('guard_value', self.var_position(op.args[0])) self.register_var(op.result) else: - xxx + log.WARNING('ignoring hint %r at %r' % (hints, self.graph)) + self.serialize_op_same_as(op) def serialize_op_int_is_true(self, op): if isinstance(op.args[0], Constant): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/policy.py Fri Feb 27 09:33:59 2009 @@ -62,8 +62,8 @@ self.fill_seen_graphs() def look_inside_graph(self, graph): - if self.enabled_graphs.get(graph): - return True + if graph in self.enabled_graphs: + return self.enabled_graphs[graph] return super(ManualJitPolicy, self).look_inside_graph(graph) def fill_seen_graphs(self): Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Feb 27 09:33:59 2009 @@ -243,7 +243,7 @@ return self.execute_with_exc(%r, [b1, b2], "int", True) ''' % (_opimpl, _opimpl)).compile() - for _opimpl in ['int_is_true', 'int_neg', 'bool_not', + for _opimpl in ['int_is_true', 'int_neg', 'int_invert', 'bool_not', ]: exec py.code.Source(''' @arguments("box") @@ -251,6 +251,14 @@ self.execute(%r, [b], "int", True) ''' % (_opimpl, _opimpl)).compile() + for _opimpl in ['int_neg_ovf', + ]: + exec py.code.Source(''' + @arguments("box") + def opimpl_%s(self, b): + return self.execute_with_exc(%r, [b], "int", True) + ''' % (_opimpl, _opimpl)).compile() + @arguments() def opimpl_return(self): assert len(self.env) == 1 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Fri Feb 27 09:33:59 2009 @@ -122,6 +122,11 @@ _ll_2_list_getitem_foldable = _ll_2_list_getitem _ll_1_list_len_foldable = _ll_1_list_len +def _ll_0_newdict(DICT): + from pypy.rpython.lltypesystem.rdict import ll_newdict + return ll_newdict(DICT) +_ll_0_newdict.need_result_type = True + _ll_2_dict_getitem = rdict.ll_dict_getitem _ll_3_dict_setitem = rdict.ll_dict_setitem _ll_2_dict_contains = rdict.ll_contains Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py Fri Feb 27 09:33:59 2009 @@ -578,6 +578,7 @@ res = rstr.ll_strconcat(res, ll_int2hex(uid, False)) res = rstr.ll_strconcat(res, rstr.instance_str_suffix) return res + ll_str._look_inside_me_ = False def rtype_isinstance(self, hop): class_repr = get_type_repr(hop.rtyper) Modified: pypy/branch/pyjitpl5/pypy/translator/goal/ann_override.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/translator/goal/ann_override.py (original) +++ pypy/branch/pyjitpl5/pypy/translator/goal/ann_override.py Fri Feb 27 09:33:59 2009 @@ -164,20 +164,16 @@ return CACHED_LOOKUP = """ -from pypy.rlib.jit import hint def lookup_%(attr)s(space, w_obj, name): w_type = space.type(w_obj) if not w_type.is_heaptype(): - w_type = hint(w_type, deepfreeze=True) return w_type.cached_%(attr)s return w_type.lookup("%(attr)s") """ CACHED_LOOKUP_IN_TYPE_WHERE = """ -from pypy.rlib.jit import hint def lookup_in_type_where_%(attr)s(space, w_type, name): if not w_type.is_heaptype(): - w_type = hint(w_type, deepfreeze=True) return w_type.cached_where_%(attr)s return w_type.lookup_where("%(attr)s") """ From arigo at codespeak.net Fri Feb 27 10:35:10 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 10:35:10 +0100 (CET) Subject: [pypy-svn] r62206 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090227093510.E7059168477@codespeak.net> Author: arigo Date: Fri Feb 27 10:35:10 2009 New Revision: 62206 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: Add int_lshift. When the llgraph backend crashes, make it pause with a pdb for now. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Feb 27 10:35:10 2009 @@ -47,6 +47,7 @@ TYPES = { 'int_add' : (('int', 'int'), 'int'), 'int_mod' : (('int', 'int'), 'int'), + 'int_lshift' : (('int', 'int'), 'int'), 'int_rshift' : (('int', 'int'), 'int'), 'int_and' : (('int', 'int'), 'int'), 'int_sub' : (('int', 'int'), 'int'), @@ -482,6 +483,7 @@ raise e.args[0] except Exception, e: log.ERROR('%s in CPU frame: %s' % (e.__class__.__name__, e)) + import sys, pdb; pdb.post_mortem(sys.exc_info()[2]) raise return result From arigo at codespeak.net Fri Feb 27 10:44:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 10:44:45 +0100 (CET) Subject: [pypy-svn] r62208 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test Message-ID: <20090227094445.A033F16847C@codespeak.net> Author: arigo Date: Fri Feb 27 10:44:45 2009 New Revision: 62208 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Log: Port or skip these tests. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/test/test_llgraph.py Fri Feb 27 10:44:45 2009 @@ -3,9 +3,9 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rlib.unroll import unrolling_iterable -from history import BoxInt, BoxPtr, Const, ConstInt -from history import ResOperation, MergePoint, Jump -from llgraph.runner import CPU, GuardFailed +from pypy.jit.metainterp.history import BoxInt, BoxPtr, Const, ConstInt +from pypy.jit.metainterp.history import ResOperation, MergePoint, Jump +from pypy.jit.backend.llgraph.runner import CPU, GuardFailed class FakeMetaInterp(object): @@ -15,8 +15,8 @@ assert isinstance(gf, GuardFailed) self.gf = gf self.recordedvalues = [ - self.cpu.getvaluebox(gf.frame, gf.merge_point, i).value - for i in range(len(gf.merge_point.args))] + self.cpu.getvaluebox(gf.frame, gf.guard_op, i).value + for i in range(len(gf.guard_op.liveboxes))] gf.make_ready_for_return(BoxInt(42)) NODE = lltype.GcForwardReference() @@ -52,16 +52,16 @@ def test_execute_operation(self): cpu = CPU(None) node = lltype.malloc(NODE) - node_value = cpu.offsetof(NODE, 'value') + node_value = cpu.fielddescrof(NODE, 'value') nodeadr = lltype.cast_opaque_ptr(llmemory.GCREF, node) - box = cpu.execute_operation('setfield_gc__4', [BoxPtr(nodeadr), - ConstInt(node_value), - BoxInt(3)], + box = cpu.execute_operation('setfield_gc', [BoxPtr(nodeadr), + ConstInt(node_value), + BoxInt(3)], 'void') assert box is None assert node.value == 3 - box = cpu.execute_operation('getfield_gc__4', [BoxPtr(nodeadr), + box = cpu.execute_operation('getfield_gc', [BoxPtr(nodeadr), ConstInt(node_value)], 'int') assert box.value == 3 @@ -79,25 +79,24 @@ ResOperation('int_add', [x, y], [z]), ResOperation('int_sub', [y, ConstInt(1)], [t]), ResOperation('int_eq', [t, ConstInt(0)], [u]), - MergePoint('merge_point', [t, u, z], []), ResOperation('guard_false', [u], []), Jump('jump', [z, t], []), ] + operations[-2].liveboxes = [t, z] startmp = operations[0] - othermp = operations[-3] operations[-1].jump_target = startmp cpu.compile_operations(operations) res = cpu.execute_operations_in_new_frame('foo', startmp, [BoxInt(0), BoxInt(10)]) assert res.value == 42 gf = cpu.metainterp.gf - assert gf.merge_point is othermp - assert cpu.metainterp.recordedvalues == [0, 1, 55] + assert cpu.metainterp.recordedvalues == [0, 55] assert gf.guard_op is operations[-2] assert cpu.stats.exec_counters['int_add'] == 10 assert cpu.stats.exec_jumps == 9 def test_passing_guards(self): + py.test.skip("rewrite me") cpu = CPU(None) assert cpu.execute_operation('guard_true', [BoxInt(1)], 'void') == None assert cpu.execute_operation('guard_false',[BoxInt(0)], 'void') == None @@ -110,6 +109,7 @@ #assert cpu.stats.exec_jumps == 0 def test_failing_guards(self): + py.test.skip("rewrite me") cpu = CPU(None) cpu.set_meta_interp(FakeMetaInterp(cpu)) #node = ootype.new(NODE) @@ -144,6 +144,7 @@ assert cpu.cast_int_to_adr(0) == llmemory.NULL def test_llinterp_simple(self): + py.test.skip("rewrite me") cpu = CPU(None) self.eval_llinterp(cpu.execute_operation, "int_sub", [BoxInt(10), BoxInt(2)], "int", From arigo at codespeak.net Fri Feb 27 10:46:39 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 10:46:39 +0100 (CET) Subject: [pypy-svn] r62209 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090227094639.4A8CB16847C@codespeak.net> Author: arigo Date: Fri Feb 27 10:46:38 2009 New Revision: 62209 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: Add operations and regroup. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Feb 27 10:46:38 2009 @@ -46,12 +46,15 @@ # very useful TYPES = { 'int_add' : (('int', 'int'), 'int'), + 'int_sub' : (('int', 'int'), 'int'), + 'int_mul' : (('int', 'int'), 'int'), + 'int_floordiv' : (('int', 'int'), 'int'), 'int_mod' : (('int', 'int'), 'int'), + 'int_and' : (('int', 'int'), 'int'), + 'int_or' : (('int', 'int'), 'int'), + 'int_xor' : (('int', 'int'), 'int'), 'int_lshift' : (('int', 'int'), 'int'), 'int_rshift' : (('int', 'int'), 'int'), - 'int_and' : (('int', 'int'), 'int'), - 'int_sub' : (('int', 'int'), 'int'), - 'int_mul' : (('int', 'int'), 'int'), 'int_lt' : (('int', 'int'), 'bool'), 'int_gt' : (('int', 'int'), 'bool'), 'int_ge' : (('int', 'int'), 'bool'), From hpk at codespeak.net Fri Feb 27 11:24:20 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 27 Feb 2009 11:24:20 +0100 (CET) Subject: [pypy-svn] r62212 - in pypy/trunk/pypy: config doc Message-ID: <20090227102420.4B5A7168046@codespeak.net> Author: hpk Date: Fri Feb 27 11:24:19 2009 New Revision: 62212 Modified: pypy/trunk/pypy/config/makerestdoc.py pypy/trunk/pypy/doc/confrest.py pypy/trunk/pypy/doc/conftest.py pypy/trunk/pypy/doc/test_redirections.py Log: Some fixes related to the pytestplugin branch merge: most everything should continue to work, except pypy/doc/ with its conftest and confrest files which are now quite clean and small by means of using the new "pytest_restdoc" plugin. Modified: pypy/trunk/pypy/config/makerestdoc.py ============================================================================== --- pypy/trunk/pypy/config/makerestdoc.py (original) +++ pypy/trunk/pypy/config/makerestdoc.py Fri Feb 27 11:24:19 2009 @@ -208,3 +208,48 @@ return content +def register_config_role(docdir): + """ register a :config: ReST link role for use in documentation. """ + try: + from docutils.parsers.rst import directives, states, roles + from py.__.rest.directive import register_linkrole + except ImportError: + return + # enable :config: link role + def config_role(name, rawtext, text, lineno, inliner, options={}, + content=[]): + from docutils import nodes + from pypy.config.pypyoption import get_pypy_config + from pypy.config.makerestdoc import get_cmdline + txt = docdir.join("config", text + ".txt") + html = docdir.join("config", text + ".html") + assert txt.check() + assert name == "config" + sourcedir = py.path.local(inliner.document.settings._source).dirpath() + curr = sourcedir + prefix = "" + while 1: + relative = str(html.relto(curr)) + if relative: + break + curr = curr.dirpath() + prefix += "../" + config = get_pypy_config() + # begin horror + h, n = config._cfgimpl_get_home_by_path(text) + opt = getattr(h._cfgimpl_descr, n) + # end horror + cmdline = get_cmdline(opt.cmdline, text) + if cmdline is not None: + shortest_long_option = 'X'*1000 + for cmd in cmdline.split(): + if cmd.startswith('--') and len(cmd) < len(shortest_long_option): + shortest_long_option = cmd + text = shortest_long_option + target = prefix + relative + print text, target + reference_node = nodes.reference(rawtext, text, name=text, refuri=target) + return [reference_node], [] + config_role.content = True + config_role.options = {} + roles.register_canonical_role("config", config_role) Modified: pypy/trunk/pypy/doc/confrest.py ============================================================================== --- pypy/trunk/pypy/doc/confrest.py (original) +++ pypy/trunk/pypy/doc/confrest.py Fri Feb 27 11:24:19 2009 @@ -1,5 +1,8 @@ import py -from py.__.doc.confrest import * + +# XXX importing/inheriting from an internal py lib class is hackish +from py.__.doc.confrest import Project, Page, relpath +html = py.xml.html class PyPyPage(Page): def fill_menubar(self): @@ -27,7 +30,8 @@ def get_doclink(self, target): return relpath(self.targetpath.strpath, - self.project.get_docpath().join(target).strpath) + self.project.docpath.join(target).strpath) + class Project(Project): mydir = py.magic.autopath().dirpath() @@ -42,6 +46,3 @@ src="http://codespeak.net/pypy/img/py-web1.png", height=110, width=149))) Page = PyPyPage - - def get_docpath(self): - return self.mydir Modified: pypy/trunk/pypy/doc/conftest.py ============================================================================== --- pypy/trunk/pypy/doc/conftest.py (original) +++ pypy/trunk/pypy/doc/conftest.py Fri Feb 27 11:24:19 2009 @@ -1,85 +1,32 @@ import py -from py.__.doc.conftest import Directory, DoctestText, DocfileTests -thisdir = py.magic.autopath().dirpath() +from pypy.config.makerestdoc import register_config_role +docdir = py.magic.autopath().dirpath() -Option = py.test.config.Option -option = py.test.config.addoptions("pypy-doc options", - Option('--generate-redirections', action="store_true", - dest="generateredirections", - default=True, help="Generate the redirecting HTML files"), - Option('--enable-doctests', action="store_true", - dest="doctests", - default=False, help="enable doctests in .txt files"), - ) +pytest_plugins = "pytest_restdoc" -class PyPyDoctestText(DoctestText): - def runtest(self): - if not option.doctests: - py.test.skip("specify --enable-doctests to run doctests") - super(PyPyDoctestText, self).runtest() - - def getcontent(self): - # XXX execute PyPy prompts as well - # but for now just get rid of those lines +class PyPyDocPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("pypy-doc options") + group.addoption('--pypy-doctests', action="store_true", + dest="pypy_doctests", default=False, + help="enable doctests in .txt files") + group.addoption('--generate-redirections', + action="store_true", dest="generateredirections", + default=True, help="Generate redirecting HTML files") + + def pytest_configure(self, config): + self.config = config + register_config_role(docdir) + + def pytest_doctest_prepare_content(self, content): + if not self.config.getvalue("pypy_doctests"): + py.test.skip("specify --pypy-doctests to run doctests") l = [] - for line in super(PyPyDoctestText, self).getcontent().split('\n'): + for line in content.split("\n"): if line.find('>>>>') != -1: line = "" l.append(line) return "\n".join(l) -class PyPyDocfileTests(DocfileTests): - DoctestText = PyPyDoctestText - -class Directory(Directory): - DocfileTests = PyPyDocfileTests - def recfilter(self, path): - if path.basename == "statistic": - return False - return super(Directory, self).recfilter(path) - -try: - from docutils.parsers.rst import directives, states, roles - from py.__.rest.directive import register_linkrole -except ImportError: - pass -else: - # enable :config: link role - def config_role(name, rawtext, text, lineno, inliner, options={}, - content=[]): - from docutils import nodes - from pypy.config.pypyoption import get_pypy_config - from pypy.config.makerestdoc import get_cmdline - txt = thisdir.join("config", text + ".txt") - html = thisdir.join("config", text + ".html") - assert txt.check() - assert name == "config" - sourcedir = py.path.local(inliner.document.settings._source).dirpath() - curr = sourcedir - prefix = "" - while 1: - relative = str(html.relto(curr)) - if relative: - break - curr = curr.dirpath() - prefix += "../" - config = get_pypy_config() - # begin horror - h, n = config._cfgimpl_get_home_by_path(text) - opt = getattr(h._cfgimpl_descr, n) - # end horror - cmdline = get_cmdline(opt.cmdline, text) - if cmdline is not None: - shortest_long_option = 'X'*1000 - for cmd in cmdline.split(): - if cmd.startswith('--') and len(cmd) < len(shortest_long_option): - shortest_long_option = cmd - text = shortest_long_option - target = prefix + relative - print text, target - reference_node = nodes.reference(rawtext, text, name=text, refuri=target) - return [reference_node], [] - config_role.content = True - config_role.options = {} - roles.register_canonical_role("config", config_role) +ConftestPlugin = PyPyDocPlugin Modified: pypy/trunk/pypy/doc/test_redirections.py ============================================================================== --- pypy/trunk/pypy/doc/test_redirections.py (original) +++ pypy/trunk/pypy/doc/test_redirections.py Fri Feb 27 11:24:19 2009 @@ -1,6 +1,5 @@ import py -from pypy.doc.conftest import option redir = py.magic.autopath().dirpath('redirections') def checkexist(path): @@ -14,7 +13,7 @@ checkexist(newpath) # HACK: create the redirecting HTML file here... # XXX obscure fishing - if option.generateredirections and '#' not in oldname: + if py.test.config.option.generateredirections and '#' not in oldname: generate_redirection(oldname, newname) def test_eval(): From arigo at codespeak.net Fri Feb 27 11:54:17 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 11:54:17 +0100 (CET) Subject: [pypy-svn] r62213 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090227105417.CCDCC1684C6@codespeak.net> Author: arigo Date: Fri Feb 27 11:54:17 2009 New Revision: 62213 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Log: The bugs I'm working on at the moment. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Fri Feb 27 11:54:17 2009 @@ -286,6 +286,70 @@ self.check_loop_count(1) self.check_loops(int_add=0, int_mul=1, guard_class=0) + def test_indirect_call_unknown_object_1(self): + py.test.skip("XXX fix me") + myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) + def getvalue2(): + return 2 + def getvalue25(): + return 25 + def getvalue1001(): + return -1001 + def externfn(n): + if n % 5: + return getvalue2 + elif n % 7: + return getvalue25 + else: + return getvalue1001 + def f(y): + x = 0 + while y > 0: + myjitdriver.can_enter_jit(x=x, y=y) + myjitdriver.jit_merge_point(x=x, y=y) + x += externfn(y)() + y -= 1 + return x + res = self.meta_interp(f, [198], policy=StopAtXPolicy(externfn)) + assert res == f(198) + self.check_loop_count(3) + + def test_indirect_call_unknown_object_2(self): + py.test.skip("XXX fix me!!!!!!! problem in optimize.py") + myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'state']) + def getvalue2(): + return 2 + def getvalue25(): + return 25 + def getvalue1001(): + return -1001 + + class State: + count = 0 + def externfn(self, n): + assert n == 198 - self.count + self.count += 1 + if n % 5: + return getvalue2 + elif n % 7: + return getvalue25 + else: + return getvalue1001 + def f(y): + state = State() + x = 0 + while y > 0: + myjitdriver.can_enter_jit(x=x, y=y, state=state) + myjitdriver.jit_merge_point(x=x, y=y, state=state) + x += state.externfn(y)() + y -= 1 + return x + res = self.meta_interp(f, [198], + policy=StopAtXPolicy(State.externfn.im_func)) + assert res == f(198) + self.check_loop_count(3) + + class TestOOtype(SendTests, OOJitMixin): pass From fijal at codespeak.net Fri Feb 27 12:01:08 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 27 Feb 2009 12:01:08 +0100 (CET) Subject: [pypy-svn] r62214 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090227110108.B8921168489@codespeak.net> Author: fijal Date: Fri Feb 27 12:01:06 2009 New Revision: 62214 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: a harmless checkin, since this stuff is disabled anyway Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Feb 27 12:01:06 2009 @@ -432,12 +432,11 @@ @arguments("builtin", "varargs") def opimpl_newlist(self, descr, varargs): - args = [descr.malloc_func] + varargs - if len(varargs) == 1: - if descr.tp == "int": - args.append(ConstInt(0)) - else: - args.append(ConstPtr(lltype.nullptr(llmemory.GCREF.TO))) + if len(varargs) == 2: + mf = descr.malloc_3_func + else: + mf = descr.malloc_2_func + args = [mf] + varargs return self.execute_with_exc('newlist', args, 'ptr') @arguments("builtin", "varargs") From fijal at codespeak.net Fri Feb 27 12:02:12 2009 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 27 Feb 2009 12:02:12 +0100 (CET) Subject: [pypy-svn] r62215 - in pypy/branch/pyjitpl5/pypy/jit/backend/x86: . test Message-ID: <20090227110212.1AAFB16849F@codespeak.net> Author: fijal Date: Fri Feb 27 12:02:11 2009 New Revision: 62215 Added: pypy/branch/pyjitpl5/pypy/jit/backend/x86/autopath.py - copied unchanged from r61865, pypy/branch/oo-jit/pypy/jit/codegen/i386/autopath.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/viewcode.py - copied unchanged from r61865, pypy/branch/oo-jit/pypy/jit/codegen/i386/viewcode.py Removed: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_vbool.py Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_virtual.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_virtualizable.py pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_vlist.py Log: nail down a couple of bugs in register allocation. this makes most of tests just pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/TODO Fri Feb 27 12:02:11 2009 @@ -1,4 +1,2 @@ -* Kill hack for malloc_varsize by splitting it into two ops (load and set lgt) - * Kill hack for .position attr of modrm Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/assembler.py Fri Feb 27 12:02:11 2009 @@ -457,7 +457,11 @@ genop_call__4 = _new_gen_call() gen_call = _new_gen_call() genop_call_ptr = gen_call - genop_getitem = _new_gen_call() + genop_getitem = _new_gen_call() + genop_len = _new_gen_call() + genop_pop = _new_gen_call() + genop_newlist = _new_gen_call() + genop_listnonzero = _new_gen_call() def genop_call_void(self, op, arglocs): extra_on_stack = 0 @@ -476,7 +480,11 @@ # XXX add extra_on_stack? x = arglocs[0] self.mc.CALL(x) - self.mc.ADD(esp, imm(WORD * extra_on_stack)) + self.mc.ADD(esp, imm(WORD * extra_on_stack)) + + genop_append = genop_call_void + genop_setitem = genop_call_void + genop_insert = genop_call_void def genop_call__1(self, op, arglocs, resloc): self.gen_call(op, arglocs, resloc) Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/regalloc.py Fri Feb 27 12:02:11 2009 @@ -97,10 +97,10 @@ jump = operations[-1] self.startmp = mp if guard_op: - loop_consts = self._start_from_guard_op(guard_op, mp, jump) + loop_consts, sd = self._start_from_guard_op(guard_op, mp, jump) else: - loop_consts = self._compute_loop_consts(mp, jump) - self.current_stack_depth = len(mp.args) + loop_consts, sd = self._compute_loop_consts(mp, jump) + self.current_stack_depth = sd self.computed_ops = self.walk_operations(operations, loop_consts) assert not self.reg_bindings @@ -108,10 +108,15 @@ rev_stack_binds = {} self.jump_reg_candidates = {} j = 0 + sd = len(mp.args) + if len(jump.args) > sd: + sd = len(jump.args) for i in range(len(mp.args)): arg = mp.args[i] if not isinstance(arg, Const): stackpos = guard_op.stacklocs[j] + if stackpos >= sd: + sd = stackpos + 1 loc = guard_op.locs[j] if isinstance(loc, REG): self.free_regs = [reg for reg in self.free_regs if reg is not loc] @@ -121,23 +126,26 @@ rev_stack_binds[stackpos] = arg j += 1 if jump.opname != 'jump': - return {} + return {}, sd for i in range(len(jump.args)): argloc = jump.jump_target.arglocs[i] jarg = jump.args[i] - if isinstance(argloc, REG): - self.jump_reg_candidates[jarg] = argloc - if (stackpos in rev_stack_binds and - (self.longevity[rev_stack_binds[stackpos]][1] > - self.longevity[jarg][0])): - # variables cannot occupy the same place on stack, because they - # overlap. - pass # we don't care that they occupy the same place - else: - #self.dirty_stack[jarg] = True - # XXX ^^^^^^^^^ why? - self.stack_bindings[jarg] = stack_pos(i) - return {} + if not isinstance(jarg, Const): + if isinstance(argloc, REG): + self.jump_reg_candidates[jarg] = argloc + if (i in rev_stack_binds and + (self.longevity[rev_stack_binds[i]][1] > + self.longevity[jarg][0])): + # variables cannot occupy the same place on stack, + # because they overlap, but we care only in consider_jump + pass + else: + # optimization for passing around values + if jarg not in self.stack_bindings: + self.dirty_stack[jarg] = True + self.stack_bindings[jarg] = stack_pos(i) + j += 1 + return {}, sd def _compute_loop_consts(self, mp, jump): self.jump_reg_candidates = {} @@ -157,13 +165,13 @@ if free_regs: self.jump_reg_candidates[jarg] = free_regs.pop() if self.longevity[arg][1] <= self.longevity[jarg][0]: - self.stack_bindings[jarg] = stack_pos(i) - self.dirty_stack[jarg] = True + if jarg not in self.stack_bindings: + self.stack_bindings[jarg] = stack_pos(i) + self.dirty_stack[jarg] = True else: # these are loop consts, but we need stack space anyway self.stack_bindings[jarg] = stack_pos(i) - self.dirty_stack[jarg] = True - return loop_consts + return loop_consts, len(mp.args) def _check_invariants(self): if not we_are_translated(): @@ -176,6 +184,11 @@ for reg in self.free_regs: assert reg not in rev_regs assert len(rev_regs) + len(self.free_regs) == len(REGS) + for v, val in self.stack_bindings.items(): + if (isinstance(v, Box) and (v not in self.reg_bindings) and + self.longevity[v][1] > self.position and + self.longevity[v][0] <= self.position): + assert not v in self.dirty_stack def walk_operations(self, operations, loop_consts): # first pass - walk along the operations in order to find @@ -303,6 +316,8 @@ if isinstance(arg, Box): stacklocs.append(self.stack_loc(arg).position) locs.append(self.loc(arg)) + if not we_are_translated(): + assert len(dict.fromkeys(stacklocs)) == len(stacklocs) guard_op.stacklocs = stacklocs guard_op.locs = locs return locs @@ -457,7 +472,7 @@ def consider_guard_no_exception(self, op): locs = self._locs_from_liveboxes(op) self.eventually_free_vars(op.liveboxes) - return [PerformDiscard(op, locs)] + return [] consider_guard_true = consider_guard consider_guard_false = consider_guard @@ -658,8 +673,17 @@ consider_getfield_raw = consider_getfield_gc consider_getfield_raw = consider_getfield_gc - def consider_getitem(self, op): + def _consider_listop(self, op): return self._call(op, [self.loc(arg) for arg in op.args]) + + consider_getitem = _consider_listop + consider_len = _consider_listop + consider_append = _consider_listop + consider_pop = _consider_listop + consider_setitem = _consider_listop + consider_newlist = _consider_listop + consider_insert = _consider_listop + consider_listnonzero = _consider_listop def consider_zero_gc_pointers_inside(self, op): self.eventually_free_var(op.args[0]) @@ -717,13 +741,14 @@ def consider_jump(self, op): ops = [] laterops = [] + middle_ops = [] for i in range(len(op.args)): arg = op.args[i] + mp = op.jump_target + res = mp.arglocs[i] if not (isinstance(arg, Const) or (arg in self.loop_consts and self.loop_consts[arg] == i)): - mp = op.jump_target assert isinstance(mp, MergePoint) - res = mp.arglocs[i] if arg in self.reg_bindings: if not isinstance(res, REG): ops.append(Store(arg, self.loc(arg), self.stack_bindings[arg])) @@ -742,14 +767,20 @@ else: ops.append(Load(arg, self.loc(arg), res)) else: - assert arg in self.stack_bindings - if isinstance(res, REG): - laterops.append(Load(arg, self.loc(arg), res)) + if arg not in self.stack_bindings: + # we can load it correctly, because we don't care + # any more about the previous var staying there + assert not isinstance(res, REG) + ops.append(Store(arg, self.loc(arg), res)) else: - # otherwise it's correct - if not we_are_translated(): - assert repr(self.stack_bindings[arg]) == repr(res) - assert arg not in self.dirty_stack + assert arg not in self.dirty_stack + if isinstance(res, REG): + laterops.append(Load(arg, self.loc(arg), res)) + else: + if not we_are_translated(): + assert repr(res) == repr(self.loc(arg)) + elif isinstance(arg, Const): + laterops.append(Load(arg, self.loc(arg), res)) self.eventually_free_vars(op.args) return ops + laterops + [PerformDiscard(op, [])] Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_basic.py Fri Feb 27 12:02:11 2009 @@ -14,7 +14,7 @@ class TestBasic(Jit386Mixin, test_basic.BasicTests): # for the individual tests see - # ====> ../../test/test_basic.py + # ====> ../../../metainterp/test/test_basic.py def test_bug(self): jitdriver = JitDriver(greens = [], reds = ['n']) class X(object): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_regalloc.py Fri Feb 27 12:02:11 2009 @@ -98,3 +98,6 @@ 'int') assert res.value == 42 assert meta_interp.recordedvalues == f() + +def test_xxx(): + pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_slist.py Fri Feb 27 12:02:11 2009 @@ -1,6 +1,6 @@ -from test.test_slist import ListTests -from codegen386.test.test_basic import Jit386Mixin +from pypy.jit.metainterp.test.test_slist import ListTests +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin class TestSList(Jit386Mixin, ListTests): pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_symbolic.py Fri Feb 27 12:02:11 2009 @@ -1,5 +1,5 @@ -from codegen386.symbolic import * -from codegen386.runner import CPU386 +from pypy.jit.backend.x86.symbolic import * +from pypy.jit.backend.x86.runner import CPU386 from pypy.rpython.lltypesystem import lltype, rffi class FakeStats(object): Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tl.py Fri Feb 27 12:02:11 2009 @@ -1,6 +1,10 @@ -from test.test_tl import ToyLanguageTests -from codegen386.test.test_basic import Jit386Mixin + +import py +from pypy.jit.metainterp.test.test_tl import ToyLanguageTests +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin class TestTL(Jit386Mixin, ToyLanguageTests): + # for the individual tests see + # ====> ../../../metainterp/test/test_tl.py pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_tlc.py Fri Feb 27 12:02:11 2009 @@ -1,5 +1,6 @@ import py +py.test.skip("XXX") from codegen386.test.test_basic import Jit386Mixin from test.test_tlc import TLCTests from pypy.jit.tl import tlc Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_virtual.py Fri Feb 27 12:02:11 2009 @@ -1,12 +1,12 @@ -from test.test_virtual import VirtualTests -from codegen386.test.test_basic import Jit386Mixin +from pypy.jit.metainterp.test.test_virtual import VirtualTests +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin class MyClass: pass class TestsVirtual(Jit386Mixin, VirtualTests): # for the individual tests see - # ====> ../../test/test_virtual.py + # ====> ../../../metainterp/test/test_virtual.py _new_op = 'new_with_vtable' @staticmethod Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_virtualizable.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_virtualizable.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_virtualizable.py Fri Feb 27 12:02:11 2009 @@ -1,9 +1,7 @@ import py -from test.test_virtualizable import TestLLtype as BaseTest -from codegen386.test.test_basic import Jit386Mixin +from pypy.jit.metainterp.test.test_virtualizable import ImplicitVirtualizableTests +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin -py.test.skip("xxx") - -class TestVirtualizable(Jit386Mixin, BaseTest): +class TestVirtualizable(Jit386Mixin, ImplicitVirtualizableTests): pass Modified: pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/x86/test/test_vlist.py Fri Feb 27 12:02:11 2009 @@ -1,6 +1,8 @@ -from test.test_vlist import ListTests -from codegen386.test.test_basic import Jit386Mixin +from pypy.jit.metainterp.test.test_vlist import ListTests +from pypy.jit.backend.x86.test.test_basic import Jit386Mixin class TestVList(Jit386Mixin, ListTests): + # for individual tests see + # ====> ../../../metainterp/test/test_vlist.py pass From arigo at codespeak.net Fri Feb 27 12:12:00 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 12:12:00 +0100 (CET) Subject: [pypy-svn] r62216 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090227111200.E88D5168489@codespeak.net> Author: arigo Date: Fri Feb 27 12:12:00 2009 New Revision: 62216 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Log: Print more information to know what is being done with each ENTER/LEAVE pair (i.e. each tracing operation). Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py Fri Feb 27 12:12:00 2009 @@ -45,6 +45,7 @@ # the following is not translatable def _compile_new_loop_1(metainterp, loop, old_loops, endliveboxes): + orgloop = loop try: try: loop = compile_fresh_loop(metainterp, loop, old_loops, @@ -53,13 +54,17 @@ show_loop(metainterp, loop, loop.operations[0], exc) raise else: - show_loop(metainterp, loop, loop.operations[0], None) + if loop == orgloop: + show_loop(metainterp, loop, loop.operations[0], None) + else: + log.info("reusing loop at %r" % (loop,)) except optimize.CancelInefficientLoop: return None loop.check_consistency() return loop def _compile_new_bridge_1(metainterp, bridge, old_loops, endliveboxes): + orgbridge = bridge try: try: bridge = compile_fresh_bridge(metainterp, bridge, old_loops, @@ -68,7 +73,12 @@ show_loop(metainterp, bridge, None, exc) raise else: - show_loop(metainterp, bridge, None, None) + if bridge == orgbridge: + show_loop(metainterp, bridge, None, None) + elif bridge is not None: + log.info("reusing bridge at %r" % (bridge,)) + else: + log.info("compile_fresh_bridge() returned None") except optimize.CancelInefficientLoop: return None if bridge is not None: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Feb 27 12:12:00 2009 @@ -464,9 +464,9 @@ args = [descr.nonzero_func] + varargs return self.execute_with_exc('listnonzero', args, 'int') - @arguments("indirectcallset", "box", "varargs") - def opimpl_indirect_call(self, indirectcallset, box, varargs): - assert isinstance(box, Const) # XXX + @arguments("orgpc", "indirectcallset", "box", "varargs") + def opimpl_indirect_call(self, pc, indirectcallset, box, varargs): + box = self.implement_guard_value(pc, box) cpu = self.metainterp.cpu jitcode = indirectcallset.bytecode_for_address(box.getaddr(cpu)) f = self.metainterp.newframe(jitcode) @@ -776,18 +776,22 @@ def interpret(self): # Execute the frames forward until we raise a DoneWithThisFrame, # a ContinueRunningNormally, or a GenerateMergePoint exception. + if isinstance(self.history, history.BlackHole): + text = ' (BlackHole)' + else: + text = '' if not we_are_translated(): - history.log.event('ENTER') + history.log.event('ENTER' + text) else: - debug_print('ENTER') + debug_print('ENTER' + text) try: while True: self.framestack[-1].run_one_step() finally: if not we_are_translated(): - history.log.event('LEAVE') + history.log.event('LEAVE' + text) else: - debug_print('LEAVE') + debug_print('LEAVE' + text) def compile_and_run(self, *args): orig_boxes = self.initialize_state_from_start(*args) From arigo at codespeak.net Fri Feb 27 12:15:10 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 12:15:10 +0100 (CET) Subject: [pypy-svn] r62217 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090227111510.8176A1683FF@codespeak.net> Author: arigo Date: Fri Feb 27 12:15:10 2009 New Revision: 62217 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Log: Fix test_indirect_call_unknown_object_1. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 27 12:15:10 2009 @@ -435,8 +435,10 @@ elif opname == 'guard_value': instnode = self.getnode(op.args[0]) assert isinstance(op.args[1], Const) - self.nodes[instnode.source] = InstanceNode(op.args[1], - const=True) + # XXX need to think more about the 'const' attribute + # (see test_send.test_indirect_call_unknown_object_1) + #self.nodes[instnode.source] = InstanceNode(op.args[1], + # const=True) continue elif opname == 'guard_nonvirtualized': instnode = self.getnode(op.args[0]) @@ -669,14 +671,14 @@ if opname == 'guard_true' or opname == 'guard_false': if self.nodes[op.args[0]].const: continue - if (opname == 'guard_no_exception' or - opname == 'guard_exception'): + elif (opname == 'guard_no_exception' or + opname == 'guard_exception'): if not exception_might_have_happened: continue exception_might_have_happened = False - if opname == 'guard_value': - if (self.nodes[op.args[0]].const and - self.nodes[op.args[1]].const): + elif opname == 'guard_value': + if self.nodes[op.args[0]].const: + assert isinstance(op.args[1], Const) continue op = self.optimize_guard(op) newoperations.append(op) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_send.py Fri Feb 27 12:15:10 2009 @@ -287,7 +287,6 @@ self.check_loops(int_add=0, int_mul=1, guard_class=0) def test_indirect_call_unknown_object_1(self): - py.test.skip("XXX fix me") myjitdriver = JitDriver(greens = [], reds = ['x', 'y']) def getvalue2(): return 2 From arigo at codespeak.net Fri Feb 27 12:19:19 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 12:19:19 +0100 (CET) Subject: [pypy-svn] r62218 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090227111919.48AA6168405@codespeak.net> Author: arigo Date: Fri Feb 27 12:19:18 2009 New Revision: 62218 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Log: Fix test_can_enter_jit_outside_main_loop when run via test_loop_spec. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 27 12:19:18 2009 @@ -471,12 +471,15 @@ end_args = self.loop.operations[-1].args memo = {} for i in range(len(end_args)): - self.nodes[end_args[i]].escape_if_startbox(memo) + end_box = end_args[i] + if isinstance(end_box, Box): + self.nodes[end_box].escape_if_startbox(memo) for i in range(len(end_args)): box = self.loop.operations[0].args[i] other_box = end_args[i] - self.nodes[box].add_to_dependency_graph(self.nodes[other_box], - self.dependency_graph) + if isinstance(other_box, Box): + self.nodes[box].add_to_dependency_graph(self.nodes[other_box], + self.dependency_graph) # XXX find efficient algorithm, we're too fried for that by now done = False while not done: From hpk at codespeak.net Fri Feb 27 12:43:10 2009 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 27 Feb 2009 12:43:10 +0100 (CET) Subject: [pypy-svn] r62219 - pypy/trunk/pypy Message-ID: <20090227114310.BA7601684A7@codespeak.net> Author: hpk Date: Fri Feb 27 12:43:10 2009 New Revision: 62219 Modified: pypy/trunk/pypy/conftest.py Log: introduce PyPyTestPlugin, and other bits to avoid deprecation warnings Modified: pypy/trunk/pypy/conftest.py ============================================================================== --- pypy/trunk/pypy/conftest.py (original) +++ pypy/trunk/pypy/conftest.py Fri Feb 27 12:43:10 2009 @@ -18,7 +18,6 @@ # PyPy's command line extra options (these are added # to py.test's standard options) # -Option = py.test.config.Option def _set_platform(opt, opt_str, value, parser): from pypy.config.translationoption import PLATFORMS @@ -27,20 +26,23 @@ raise ValueError("%s not in %s" % (value, PLATFORMS)) set_platform(value, None) -option = py.test.config.addoptions("pypy options", - Option('--view', action="store_true", dest="view", default=False, - help="view translation tests' flow graphs with Pygame"), - Option('-A', '--runappdirect', action="store_true", +option = py.test.config.option + +class PyPyTestPlugin: + def pytest_addoption(self, parser): + group = parser.addgroup("pypy option") + group.addoption('--view', action="store_true", dest="view", default=False, + help="view translation tests' flow graphs with Pygame") + group.addoption('-A', '--runappdirect', action="store_true", default=False, dest="runappdirect", - help="run applevel tests directly on python interpreter (not through PyPy)"), - Option('--direct', action="store_true", + help="run applevel tests directly on python interpreter (not through PyPy)") + group.addoption('--direct', action="store_true", default=False, dest="rundirect", - help="run pexpect tests directly"), - Option('-P', '--platform', action="callback", type="string", + help="run pexpect tests directly") + group.addoption('-P', '--platform', action="callback", type="string", default="host", callback=_set_platform, - help="set up tests to use specified platform as compile/run target"), - ) - + help="set up tests to use specified platform as compile/run target") +ConftestPlugin = PyPyTestPlugin _SPACECACHE={} def gettestobjspace(name=None, **kwds): @@ -505,11 +507,11 @@ class Directory(py.test.collect.Directory): - def consider_dir(self, path, usefilters=True): + def consider_dir(self, path): if path == rootdir.join("lib", "ctypes", "test"): py.test.skip("These are the original ctypes tests.\n" "You can try to run them with 'pypy-c runtests.py'.") - return super(Directory, self).consider_dir(path, usefilters=usefilters) + return super(Directory, self).consider_dir(path) def recfilter(self, path): # disable recursion in symlinked subdirectories From arigo at codespeak.net Fri Feb 27 13:16:16 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 13:16:16 +0100 (CET) Subject: [pypy-svn] r62220 - pypy/branch/pyjitpl5 Message-ID: <20090227121616.31BC5168517@codespeak.net> Author: arigo Date: Fri Feb 27 13:16:15 2009 New Revision: 62220 Modified: pypy/branch/pyjitpl5/ (props changed) Log: Disable updating of the py lib in this branch. From arigo at codespeak.net Fri Feb 27 13:51:47 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 13:51:47 +0100 (CET) Subject: [pypy-svn] r62221 - in pypy/branch/pyjitpl5/pypy/jit: metainterp tl Message-ID: <20090227125147.722D9168501@codespeak.net> Author: arigo Date: Fri Feb 27 13:51:46 2009 New Revision: 62221 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: - fix a bug in optimize.py. - add the exception-catching logic that allowed me to locate this bug. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 27 13:51:46 2009 @@ -762,15 +762,15 @@ ## self.optimize_setfield(instnode, ofs, valuenode, op.args[3]) ## continue elif opname == 'ooisnull' or opname == 'oononnull': - instnode = self.nodes[op.args[0]] + instnode = self.getnode(op.args[0]) if instnode.virtual: box = op.results[0] instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue elif opname == 'oois' or opname == 'ooisnot': - instnode_x = self.nodes[op.args[0]] - instnode_y = self.nodes[op.args[1]] + instnode_x = self.getnode(op.args[0]) + instnode_y = self.getnode(op.args[1]) if instnode_x.virtual or instnode_y.virtual: box = op.results[0] instnode = InstanceNode(box.constbox(), const=True) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Fri Feb 27 13:51:46 2009 @@ -126,8 +126,19 @@ state = WarmEnterState() self.state = state + def crash_in_jit(e): + print "Crash in JIT!" + print '%s: %s' % (e.__class__, e) + if not we_are_translated(): + import sys, pdb; pdb.post_mortem(sys.exc_info()[2]) + raise AssertionError("crash in JIT") + crash_in_jit._dont_inline_ = True + def maybe_enter_jit(*args): - state.maybe_compile_and_run(*args) + try: + state.maybe_compile_and_run(*args) + except Exception, e: + crash_in_jit(e) maybe_enter_jit._always_inline_ = True self.maybe_enter_jit_fn = maybe_enter_jit Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Fri Feb 27 13:51:46 2009 @@ -1,4 +1,6 @@ +print 543210 + i = 0 while i < 100: i += 3 From arigo at codespeak.net Fri Feb 27 13:57:45 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 13:57:45 +0100 (CET) Subject: [pypy-svn] r62222 - pypy/branch/pyjitpl5/pypy/jit/metainterp Message-ID: <20090227125745.2D592168447@codespeak.net> Author: arigo Date: Fri Feb 27 13:57:43 2009 New Revision: 62222 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Fix Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Fri Feb 27 13:57:43 2009 @@ -73,6 +73,9 @@ stats.maybe_view() stats.check_consistency() +class JitException(Exception): + _go_through_llinterp_uncaught_ = True # ugh + # ____________________________________________________________ class WarmRunnerDesc: @@ -137,6 +140,8 @@ def maybe_enter_jit(*args): try: state.maybe_compile_and_run(*args) + except JitException: + raise # go through except Exception, e: crash_in_jit(e) maybe_enter_jit._always_inline_ = True @@ -229,15 +234,13 @@ portal_ptr = lltype.functionptr(PORTALFUNC, 'portal', graph = portalgraph) - class DoneWithThisFrame(Exception): - _go_through_llinterp_uncaught_ = True # ugh + class DoneWithThisFrame(JitException): def __init__(self, resultbox): self.resultbox = resultbox def __str__(self): return 'DoneWithThisFrame(%s)' % (self.result,) - class ExitFrameWithException(Exception): - _go_through_llinterp_uncaught_ = True # ugh + class ExitFrameWithException(JitException): def __init__(self, typebox, valuebox): self.typebox = typebox self.valuebox = valuebox @@ -245,9 +248,7 @@ return 'ExitFrameWithException(%s, %s)' % (self.type, self.value) - class ContinueRunningNormally(Exception): - _go_through_llinterp_uncaught_ = True # ugh - + class ContinueRunningNormally(JitException): def __init__(self, args): self.args = args From arigo at codespeak.net Fri Feb 27 14:34:09 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 14:34:09 +0100 (CET) Subject: [pypy-svn] r62223 - in pypy/branch/pyjitpl5/pypy/jit: backend/llgraph metainterp metainterp/test Message-ID: <20090227133409.1D73D1684D6@codespeak.net> Author: arigo Date: Fri Feb 27 14:34:08 2009 New Revision: 62223 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Log: Support for unsigned variables. Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Feb 27 14:34:08 2009 @@ -9,6 +9,7 @@ from pypy.jit.metainterp.history import (ConstInt, ConstPtr, ConstAddr, BoxInt, BoxPtr) from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr +from pypy.rpython.lltypesystem import lloperation from pypy.rpython.ootypesystem import ootype from pypy.rpython.module.support import LLSupport, OOSupport from pypy.rpython.llinterp import LLInterpreter, LLFrame, LLException @@ -18,6 +19,7 @@ from pypy.jit.backend.llgraph import symbolic from pypy.rlib.objectmodel import ComputedIntSymbolic +from pypy.rlib.rarithmetic import r_uint import py from pypy.tool.ansi_print import ansi_log @@ -69,6 +71,15 @@ 'int_mul_ovf' : (('int', 'int'), 'int'), 'int_neg_ovf' : (('int',), 'int'), 'bool_not' : (('bool',), 'bool'), + 'uint_add' : (('int', 'int'), 'int'), + 'uint_sub' : (('int', 'int'), 'int'), + 'uint_mul' : (('int', 'int'), 'int'), + 'uint_lt' : (('int', 'int'), 'bool'), + 'uint_le' : (('int', 'int'), 'bool'), + 'uint_eq' : (('int', 'int'), 'bool'), + 'uint_ne' : (('int', 'int'), 'bool'), + 'uint_gt' : (('int', 'int'), 'bool'), + 'uint_ge' : (('int', 'int'), 'bool'), 'new_with_vtable' : (('int', 'ptr'), 'ptr'), 'new' : (('int',), 'ptr'), 'new_array' : (('int', 'int'), 'ptr'), @@ -573,6 +584,24 @@ # but we don't want this to occur in our case return LLFrame(graph, args, self.llinterpreter) + # ---------- signed/unsigned support ---------- + + # for these operations, allow us to be called with unsigned or with + # regular signed arguments (which would come e.g. from ConstInt) + for _opname in ['uint_add', 'uint_sub', 'uint_mul', + 'uint_lt', 'uint_le', 'uint_eq', + 'uint_ne', 'uint_gt', 'int_ge', + ]: + exec py.code.Source(""" + def op_%s(self, x, y): + x = r_uint(x) + y = r_uint(y) + ophandler = lloperation.LL_OPERATIONS[%r].fold + return ophandler(x, y) + """ % (_opname, _opname)).compile() + + # ---------------------------------------- + def op_return(self, value=None): if self.last_exception is None: raise ExecutionReturned(value) Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py Fri Feb 27 14:34:08 2009 @@ -473,15 +473,6 @@ serialize_op_unichar_eq = serialize_op_char_eq serialize_op_unichar_ne = serialize_op_char_ne - def serialize_op_uint_add(self, op): self._defl(op, 'int_add') - def serialize_op_uint_sub(self, op): self._defl(op, 'int_sub') - def serialize_op_uint_lt (self, op): self._defl(op, 'int_lt') - def serialize_op_uint_le (self, op): self._defl(op, 'int_le') - def serialize_op_uint_eq (self, op): self._defl(op, 'int_eq') - def serialize_op_uint_ne (self, op): self._defl(op, 'int_ne') - def serialize_op_uint_gt (self, op): self._defl(op, 'int_gt') - def serialize_op_uint_ge (self, op): self._defl(op, 'int_ge') - def serialize_op_int_add_nonneg_ovf(self, op): self.default_serialize_op(op, 'int_add_ovf') Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py Fri Feb 27 14:34:08 2009 @@ -228,6 +228,9 @@ 'int_ne', 'int_gt', 'int_ge', 'int_and', 'int_or', 'int_xor', 'int_rshift', 'int_lshift', + 'uint_add', 'uint_sub', 'uint_mul', + 'uint_lt', 'uint_le', 'uint_eq', + 'uint_ne', 'uint_gt', 'int_ge', ]: exec py.code.Source(''' @arguments("box", "box") Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Fri Feb 27 14:34:08 2009 @@ -232,6 +232,19 @@ res = self.interp_operations(f, [7]) assert res == 1212 + def test_r_uint(self): + from pypy.rlib.rarithmetic import r_uint + myjitdriver = JitDriver(greens = [], reds = ['y']) + def f(y): + y = r_uint(y) + while y > 0: + myjitdriver.can_enter_jit(y=y) + myjitdriver.jit_merge_point(y=y) + y -= 1 + return y + res = self.meta_interp(f, [10]) + assert res == 0 + class TestOOtype(BasicTests, OOJitMixin): pass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py Fri Feb 27 14:34:08 2009 @@ -272,7 +272,7 @@ if isinstance(TYPE, lltype.Ptr): return box.getptr(TYPE) else: - return box.getint() + return lltype.cast_primitive(TYPE, box.getint()) unwrap._annspecialcase_ = 'specialize:arg(0)' def ll_portal_runner(*args): @@ -317,7 +317,7 @@ vlist += greens_v vlist += reds_v v_result = Variable() - v_result.concretetype = lltype.Void + v_result.concretetype = PORTALFUNC.RESULT newop = SpaceOperation('direct_call', vlist, v_result) del origblock.operations[origindex:] origblock.operations.append(newop) From arigo at codespeak.net Fri Feb 27 14:46:04 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 14:46:04 +0100 (CET) Subject: [pypy-svn] r62224 - pypy/branch/pyjitpl5/pypy/jit/backend/llgraph Message-ID: <20090227134604.3E7CD16846D@codespeak.net> Author: arigo Date: Fri Feb 27 14:46:03 2009 New Revision: 62224 Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Log: Fix: always pass signed integers in the graphs produced by the JIT (like we always pass GCREFs instead of pointers). Muuuuch saner. Other fix: 'int_ge' -> 'uint_ge' :-( Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py Fri Feb 27 14:46:03 2009 @@ -19,7 +19,7 @@ from pypy.jit.backend.llgraph import symbolic from pypy.rlib.objectmodel import ComputedIntSymbolic -from pypy.rlib.rarithmetic import r_uint +from pypy.rlib.rarithmetic import r_uint, intmask import py from pypy.tool.ansi_print import ansi_log @@ -586,18 +586,19 @@ # ---------- signed/unsigned support ---------- - # for these operations, allow us to be called with unsigned or with - # regular signed arguments (which would come e.g. from ConstInt) + # for these operations, we expect to be called with regular ints + # and to return regular ints for _opname in ['uint_add', 'uint_sub', 'uint_mul', 'uint_lt', 'uint_le', 'uint_eq', - 'uint_ne', 'uint_gt', 'int_ge', + 'uint_ne', 'uint_gt', 'uint_ge', ]: exec py.code.Source(""" def op_%s(self, x, y): x = r_uint(x) y = r_uint(y) ophandler = lloperation.LL_OPERATIONS[%r].fold - return ophandler(x, y) + z = ophandler(x, y) + return intmask(z) """ % (_opname, _opname)).compile() # ---------------------------------------- From arigo at codespeak.net Fri Feb 27 15:47:37 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 15:47:37 +0100 (CET) Subject: [pypy-svn] r62236 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090227144737.4736F168519@codespeak.net> Author: arigo Date: Fri Feb 27 15:47:36 2009 New Revision: 62236 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Log: View the loop produced by the PyPy JIT. Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Fri Feb 27 15:47:36 2009 @@ -1,3 +1,4 @@ +from pypy.conftest import option from pypy.rpython.lltypesystem import lltype from pypy.jit.metainterp import warmspot from pypy.module.pypyjit.portal import PyPyJitPolicy @@ -14,4 +15,5 @@ print 'warmspot.jittify_and_run() started...' policy = PyPyJitPolicy(interp.typer.annotator.translator) + option.view = True warmspot.jittify_and_run(interp, graph, [], policy=policy) From arigo at codespeak.net Fri Feb 27 15:50:32 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 15:50:32 +0100 (CET) Subject: [pypy-svn] r62237 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090227145032.D235A168519@codespeak.net> Author: arigo Date: Fri Feb 27 15:50:32 2009 New Revision: 62237 Removed: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_prolog_jit.py Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Log: Remove unused imports. Remove unused test file. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_exception.py Fri Feb 27 15:50:32 2009 @@ -1,6 +1,6 @@ import py from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.rlib.jit import JitDriver, hint +from pypy.rlib.jit import JitDriver from pypy.rlib.rarithmetic import ovfcheck from pypy.jit.metainterp.policy import StopAtXPolicy Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_slist.py Fri Feb 27 15:50:32 2009 @@ -1,7 +1,7 @@ import py from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin -from pypy.rlib.jit import JitDriver, hint +from pypy.rlib.jit import JitDriver class ListTests: Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tl.py Fri Feb 27 15:50:32 2009 @@ -1,5 +1,5 @@ import py -from pypy.rlib.jit import JitDriver, hint +from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_tlc.py Fri Feb 27 15:50:32 2009 @@ -1,6 +1,5 @@ import py from pypy.rpython.module.support import LLSupport -from pypy.rlib.jit import hint from pypy.jit.tl import tlc Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtual.py Fri Feb 27 15:50:32 2009 @@ -1,5 +1,5 @@ import py -from pypy.rlib.jit import JitDriver, hint +from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin from pypy.rpython.lltypesystem import lltype, rclass Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_vlist.py Fri Feb 27 15:50:32 2009 @@ -1,7 +1,7 @@ import py py.test.skip("re-enable list optimizations") -from pypy.rlib.jit import JitDriver, hint +from pypy.rlib.jit import JitDriver from pypy.jit.metainterp.policy import StopAtXPolicy from pypy.rpython.ootypesystem import ootype from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin From arigo at codespeak.net Fri Feb 27 16:13:14 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 16:13:14 +0100 (CET) Subject: [pypy-svn] r62238 - pypy/branch/pyjitpl5/pypy/jit/metainterp/test Message-ID: <20090227151314.B6CF816852B@codespeak.net> Author: arigo Date: Fri Feb 27 16:13:13 2009 New Revision: 62238 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Log: Add two tests about getfield vs getfield_pure, triggered as the _immutable_=True hint on a class. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py Fri Feb 27 16:13:13 2009 @@ -4,6 +4,7 @@ from pypy.jit.backend.llgraph import runner from pypy.jit.metainterp import support, codewriter, pyjitpl, history from pypy.jit.metainterp.policy import JitPolicy, StopAtXPolicy +from pypy import conftest def get_metainterp(func, values, CPUClass, type_system, policy): from pypy.annotation.policy import AnnotatorPolicy @@ -65,6 +66,8 @@ try: metainterp.compile_and_run(*args) except DoneWithThisFrame, e: + if conftest.option.view: + metainterp.stats.view() return e.args[0].value else: raise Exception("FAILED") @@ -245,6 +248,40 @@ res = self.meta_interp(f, [10]) assert res == 0 + def test_getfield(self): + class A: + pass + a1 = A() + a1.foo = 5 + a2 = A() + a2.foo = 8 + def f(x): + if x > 5: + a = a1 + else: + a = a2 + return a.foo * x + res = self.interp_operations(f, [42]) + assert res == 210 + self.check_history_(getfield_gc=1) + + def test_getfield_immutable(self): + class A: + _immutable_ = True + a1 = A() + a1.foo = 5 + a2 = A() + a2.foo = 8 + def f(x): + if x > 5: + a = a1 + else: + a = a2 + return a.foo * x + res = self.interp_operations(f, [42]) + assert res == 210 + self.check_history_(getfield_gc=0) + class TestOOtype(BasicTests, OOJitMixin): pass From cfbolz at codespeak.net Fri Feb 27 16:31:44 2009 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 27 Feb 2009 16:31:44 +0100 (CET) Subject: [pypy-svn] r62242 - in pypy/branch/spy-graphic/pypy/lang/smalltalk: . test Message-ID: <20090227153144.B0D921684CB@codespeak.net> Author: cfbolz Date: Fri Feb 27 16:31:44 2009 New Revision: 62242 Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Log: Found the translation problem. Disabling it for now, working on a fix. Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/primitives.py Fri Feb 27 16:31:44 2009 @@ -592,11 +592,15 @@ import math return interp.space.wrap_int(int(math.fmod(time.time()*1000, constants.TAGGED_MAXINT/2))) + +secs_between_1901_and_1970 = rarithmetic.r_uint((69 * 365 + 17) * 24 * 3600) + @expose_primitive(SECONDS_CLOCK, unwrap_spec=[object]) def func(interp, w_arg): + return interp.space.wrap_int(73) import time - sec_since_epoch = int(time.time()) - sec_since_1901 = sec_since_epoch + ((69 * 365 + 17) * 24 * 3600) + sec_since_epoch = rarithmetic.r_uint(time.time()) + sec_since_1901 = sec_since_epoch + secs_between_1901_and_1970 return interp.space.wrap_pos_full_int(sec_since_1901) # ___________________________________________________________________________ Modified: pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/spy-graphic/pypy/lang/smalltalk/test/test_primitives.py Fri Feb 27 16:31:44 2009 @@ -392,6 +392,7 @@ prim(primitives.FULL_GC, [42]) # Dummy arg def test_seconds_clock(): + py.test.skip("disabled because it breaks translation") import time now = int(time.time()) w_smalltalk_now1 = prim(primitives.SECONDS_CLOCK, [42]) From tverwaes at codespeak.net Fri Feb 27 16:33:44 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 27 Feb 2009 16:33:44 +0100 (CET) Subject: [pypy-svn] r62243 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090227153344.467A21684CB@codespeak.net> Author: tverwaes Date: Fri Feb 27 16:33:43 2009 New Revision: 62243 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py Log: textual bug Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Fri Feb 27 16:33:43 2009 @@ -537,7 +537,7 @@ # LD (nnnn),A 4 cycles self.write(self.fetch_double_address(), self.a.get()) # 2 cycles - def store_memory_at_axpanded_fetch_address_in_a(self): + def store_memory_at_expanded_fetch_address_in_a(self): # LDH A,(nn) 3 cycles self.a.set(self.read(0xFF00 + self.fetch())) # 1+1+1 cycles @@ -909,7 +909,7 @@ (0xF9, CPU.store_hl_in_sp), (0xE0, CPU.write_a_at_expanded_fetch_address), (0xE8, CPU.increment_sp_by_fetch), - (0xF0, CPU.store_memory_at_axpanded_fetch_address_in_a), + (0xF0, CPU.store_memory_at_expanded_fetch_address_in_a), (0xF8, CPU.store_fetch_added_sp_in_hl), (0xCB, CPU.fetch_execute), (0xCD, CPU.unconditional_call), From arigo at codespeak.net Fri Feb 27 17:41:47 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 17:41:47 +0100 (CET) Subject: [pypy-svn] r62246 - in pypy/branch/pyjitpl5/pypy: interpreter jit/metainterp jit/tl Message-ID: <20090227164147.6A57616852D@codespeak.net> Author: arigo Date: Fri Feb 27 17:41:45 2009 New Revision: 62246 Modified: pypy/branch/pyjitpl5/pypy/interpreter/eval.py pypy/branch/pyjitpl5/pypy/interpreter/pycode.py pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Log: Minor tweaks. Add the _immutable_=True flag on the PyCode class. Modified: pypy/branch/pyjitpl5/pypy/interpreter/eval.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/eval.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/eval.py Fri Feb 27 17:41:45 2009 @@ -9,6 +9,7 @@ class Code(Wrappable): """A code is a compiled version of some source code. Abstract base class.""" + _immutable_ = True hidden_applevel = False # n >= 0 : arity Modified: pypy/branch/pyjitpl5/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/interpreter/pycode.py (original) +++ pypy/branch/pyjitpl5/pypy/interpreter/pycode.py Fri Feb 27 17:41:45 2009 @@ -52,6 +52,7 @@ class PyCode(eval.Code): "CPython-style code objects." + _immutable_ = True def __init__(self, space, argcount, nlocals, stacksize, flags, code, consts, names, varnames, filename, Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py Fri Feb 27 17:41:45 2009 @@ -36,6 +36,12 @@ return "_%d" % cpu.numof(TYPE) return "ptr" +def repr_pointer(box): + try: + return '*%s' % (box.value._obj.container._TYPE._name,) + except AttributeError: + return box.value + class AbstractValue(object): __slots__ = () @@ -190,8 +196,7 @@ def equals(self, other): return self.value == other.getptr_base() - def _getrepr_(self): - return self.value + _getrepr_ = repr_pointer class Box(AbstractValue): __slots__ = () @@ -266,11 +271,7 @@ def get_(self): return lltype.cast_ptr_to_int(self.value) - def _getrepr_(self): - try: - return self.value.ptr - except AttributeError: - return self.value + _getrepr_ = repr_pointer NULLBOX = BoxPtr() Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit.py Fri Feb 27 17:41:45 2009 @@ -7,6 +7,7 @@ from pypy.objspace.std import Space from pypy.config.translationoption import set_opt_level from pypy.config.pypyoption import get_pypy_config, set_pypy_opt_level +from pypy.objspace.std import multimethod config = get_pypy_config(translating=True) config.translation.backendopt.inline_threshold = 0 @@ -16,8 +17,11 @@ config.objspace.allworkingmodules = False config.objspace.usemodules.pypyjit = True set_pypy_opt_level(config, level='0') +config.objspace.std.multimethods = 'doubledispatch' +multimethod.Installer = multimethod.InstallerVersion1 print config + space = Space(config) w_dict = space.newdict() Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_demo.py Fri Feb 27 17:41:45 2009 @@ -1,7 +1,10 @@ -print 543210 +def f(): + print 543210 -i = 0 -while i < 100: - i += 3 -print i # should print 102 + i = 0 + while i < 100: + i += 3 + print i # should print 102 + +f() From arigo at codespeak.net Fri Feb 27 18:39:29 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 18:39:29 +0100 (CET) Subject: [pypy-svn] r62247 - in pypy/branch/pyjitpl5/pypy/jit/metainterp: . test Message-ID: <20090227173929.526A416852D@codespeak.net> Author: arigo Date: Fri Feb 27 18:39:27 2009 New Revision: 62247 Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Log: Improve optimize.py: detect multiple guards in sequence all checking for the class or the non-null-ness of an instance. Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/optimize.py Fri Feb 27 18:39:27 2009 @@ -642,14 +642,6 @@ op = Jump('jump', args, []) newoperations.append(op) continue - elif opname == 'guard_class': - instnode = self.nodes[op.args[0]] - if instnode.cls is not None: - assert op.args[1].equals(instnode.cls.source) - continue - op = self.optimize_guard(op) - newoperations.append(op) - continue ## elif opname == 'guard_builtin': ## instnode = self.nodes[op.args[0]] ## if instnode.cls is None: @@ -663,25 +655,31 @@ ## instnode = self.nodes[op.args[0]] ## instnode.cursize = op.args[1].getint() ## continue - elif opname == 'guard_nonvirtualized': - instnode = self.nodes[op.args[0]] - if instnode.virtualized or instnode.virtual: + elif (opname == 'guard_no_exception' or + opname == 'guard_exception'): + if not exception_might_have_happened: continue + exception_might_have_happened = False op = self.optimize_guard(op) newoperations.append(op) continue elif opname.startswith('guard_'): + instnode = self.nodes[op.args[0]] if opname == 'guard_true' or opname == 'guard_false': - if self.nodes[op.args[0]].const: + if instnode.const: continue - elif (opname == 'guard_no_exception' or - opname == 'guard_exception'): - if not exception_might_have_happened: + elif opname == 'guard_class': + if instnode.cls is not None: + assert op.args[1].equals(instnode.cls.source) continue - exception_might_have_happened = False + instnode.cls = InstanceNode(op.args[1], const=True) elif opname == 'guard_value': - if self.nodes[op.args[0]].const: - assert isinstance(op.args[1], Const) + assert isinstance(op.args[1], Const) + if instnode.const: + continue + instnode.const = True + elif opname == 'guard_nonvirtualized': + if instnode.virtualized or instnode.virtual: continue op = self.optimize_guard(op) newoperations.append(op) @@ -763,15 +761,27 @@ ## continue elif opname == 'ooisnull' or opname == 'oononnull': instnode = self.getnode(op.args[0]) - if instnode.virtual: + # we know the result is constant if instnode is a virtual, + # or if we already checked the class of the object before + if instnode.virtual or instnode.cls is not None: box = op.results[0] instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode continue + # XXX we could also do a bit better by marking on the + # InstanceNode that we compared it with NULL already elif opname == 'oois' or opname == 'ooisnot': instnode_x = self.getnode(op.args[0]) instnode_y = self.getnode(op.args[1]) - if instnode_x.virtual or instnode_y.virtual: + # we know the result is constant in one of these 4 cases: + if (instnode_x.virtual or # x is a virtual (even if y isn't) + instnode_y.virtual or # y is a virtual (even if x isn't) + (instnode_x.cls is not None and # we checked cls x and + instnode_y.const and # y is the const NULL + not instnode_y.source.getptr_base()) or + (instnode_y.cls is not None and # we checked cls y and + instnode_x.const and # x is the const NULL + not instnode_x.source.getptr_base())): box = op.results[0] instnode = InstanceNode(box.constbox(), const=True) self.nodes[box] = instnode Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_optimize.py Fri Feb 27 18:39:27 2009 @@ -759,3 +759,98 @@ ResOperation('getfield_gc', [N.n1, ConstInt(N.ofs_value)], [ANY]), Jump('jump', [N.sum2, N.n1, ANY], []), ]) + +# ____________________________________________________________ + +class O1: + locals().update(A.__dict__) # :-) + ops = [ + MergePoint('merge_point', [], []), + ResOperation('produce_somehow_n1', [], [n1]), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), + Jump('jump', [], []), + ] + ops[-3].liveboxes = [] + ops[-2].liveboxes = [] + +def test_O1_optimize_loop(): + spec = PerfectSpecializer(Loop(O1.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [], []), + ResOperation('produce_somehow_n1', [], [O1.n1]), + # only the first guard_class is left + ResOperation('guard_class', [O1.n1, ConstAddr(node_vtable, cpu), + O1.sizebox], []), + Jump('jump', [], []), + ]) + +# ____________________________________________________________ + +class O2: + locals().update(A.__dict__) # :-) + v1 = BoxInt(1) + ops = [ + MergePoint('merge_point', [], []), + ResOperation('produce_somehow_n1', [], [n1]), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), + ResOperation('oononnull', [n1], [v1]), + ResOperation('guard_true', [v1], []), + Jump('jump', [], []), + ] + ops[-4].liveboxes = [] + ops[-2].liveboxes = [] + +def test_O2_optimize_loop(): + spec = PerfectSpecializer(Loop(O2.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [], []), + ResOperation('produce_somehow_n1', [], [O2.n1]), + ResOperation('guard_class', [O2.n1, ConstAddr(node_vtable, cpu), + O2.sizebox], []), + # the oononnull and guard_true are gone, because we know they + # return True -- as there was already a guard_class done on n1 + Jump('jump', [], []), + ]) + +# ____________________________________________________________ + +class O3: + locals().update(A.__dict__) # :-) + v1 = BoxInt(1) + ops = [ + MergePoint('merge_point', [], []), + ResOperation('produce_somehow_n1', [], [n1]), + ResOperation('guard_class', [n1, ConstAddr(node_vtable, cpu), + sizebox], []), + ResOperation('oois', [n1, ConstPtr(lltype.nullptr(llmemory.GCREF.TO))], + [v1]), + ResOperation('guard_false', [v1], []), + Jump('jump', [], []), + ] + ops[-4].liveboxes = [] + ops[-2].liveboxes = [] + +def test_O3_optimize_loop(): + spec = PerfectSpecializer(Loop(O3.ops)) + spec.find_nodes() + spec.intersect_input_and_output() + spec.optimize_loop() + equaloplists(spec.loop.operations, [ + MergePoint('merge_point', [], []), + ResOperation('produce_somehow_n1', [], [O3.n1]), + ResOperation('guard_class', [O3.n1, ConstAddr(node_vtable, cpu), + O3.sizebox], []), + # the oois and guard_false are gone, because we know they + # return False -- as there was already a guard_class done on n1 + Jump('jump', [], []), + ]) From tverwaes at codespeak.net Fri Feb 27 19:05:06 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 27 Feb 2009 19:05:06 +0100 (CET) Subject: [pypy-svn] r62248 - in pypy/trunk/pypy/lang/gameboy: . debug test Message-ID: <20090227180506.B808D1684C5@codespeak.net> Author: tverwaes Date: Fri Feb 27 19:05:05 2009 New Revision: 62248 Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py pypy/trunk/pypy/lang/gameboy/debug/debug_util.py pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py pypy/trunk/pypy/lang/gameboy/video_register.py Log: change in tileData. old code didn't seem to make sense. cami should check Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Fri Feb 27 19:05:05 2009 @@ -43,21 +43,22 @@ self.print_compare(name+" value at "+hex(address), \ expected[address], new[address]) - def print_compare(self, msg, python, java, output=False): + def print_compare(self, msg, python, java, printall=False): if java != python: self.compare_failed = True print "python: !!", msg, "java:", java, "python:", python, "!!" - + if printall: + print "python: XX", msg, "java:", java, "python:", python, "!!" def print_mismatch(self, part, python, java): print "python:", str(part), "java:", str(java), "python:", str(python) - def compare_set(self, set, data, label=""): + def compare_set(self, set, data, label="", printall=False): for compare_value in set: self.print_compare(label+": "+compare_value[0], compare_value[1], - data[compare_value[2]]); + data[compare_value[2]], printall); def compare_memory_set(self, set, data, label=""): for compare_value in set: @@ -197,7 +198,7 @@ ]; for reg in mapping: display_results.append((reg[1], registers[reg[0]])) - self.print_compare("register %s" % reg[0], reg[1], registers[reg[0]], output=True) + self.print_compare("register %s" % reg[0], reg[1], registers[reg[0]]) self.print_registers(mapping, display_results) def print_registers(self, mapping, display_results): @@ -324,5 +325,4 @@ ("Check whether emulated VBLank", self.video.emulated_vblank, "emulated_vblank"), ] - self.compare_set(cmp, data, label="video") - + self.compare_set(cmp, data, label="video", printall=True) Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_util.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_util.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_util.py Fri Feb 27 19:05:05 2009 @@ -7,7 +7,7 @@ # # ---------------------------------------------------------------------------- -DEBUG = False +DEBUG = True DEBUG_PRINT_LOGS = True op_codes = [0] * (0xFF+1) fetch_execute_op_codes = [0] * (0xFF+1) Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_registers.py Fri Feb 27 19:05:05 2009 @@ -32,12 +32,13 @@ assert control.read() == i def test_video_control_get_selected_tile_data_space(): + # TODO: Cami's magic has to pass over here :) control = get_control_register() - control.window.upper_tile_map_selected = True + control.background_and_window_lower_tile_data_selected = False assert control.get_selected_tile_data_space() == constants.VRAM_DATA_B - control.window.upper_tile_map_selected = False + control.background_and_window_lower_tile_data_selected = True assert control.get_selected_tile_data_space() == constants.VRAM_DATA_A # StatusRegister --------------------------------------------------------------- Modified: pypy/trunk/pypy/lang/gameboy/video_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_register.py Fri Feb 27 19:05:05 2009 @@ -124,7 +124,7 @@ def get_selected_tile_data_space(self): - if self.window.upper_tile_map_selected: - return constants.VRAM_DATA_B - else: + if self.background_and_window_lower_tile_data_selected: return constants.VRAM_DATA_A + else: + return constants.VRAM_DATA_B From arigo at codespeak.net Fri Feb 27 19:39:38 2009 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 27 Feb 2009 19:39:38 +0100 (CET) Subject: [pypy-svn] r62249 - pypy/branch/pyjitpl5/pypy/jit/tl Message-ID: <20090227183938.DA060168541@codespeak.net> Author: arigo Date: Fri Feb 27 19:39:38 2009 New Revision: 62249 Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Log: Document the current output and the missing optimizations. Modified: pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py ============================================================================== --- pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py (original) +++ pypy/branch/pyjitpl5/pypy/jit/tl/pypyjit_child.py Fri Feb 27 19:39:38 2009 @@ -4,6 +4,28 @@ from pypy.module.pypyjit.portal import PyPyJitPolicy +# Current output: http://paste.pocoo.org/show/105784/ +# +# Some optimizations missing: +# +# - improve the optimization: e.g. ooisnull followed by oononnull +# on the same variable +# +# - reintroduce some delayed list optimizations to remove this +# mess of push/pop on the stack +# +# - remove the useless 'ec' argument (p1 and p115 in the trace) +# +# - figure out who calls W_TypeObject.is_heaptype(), leading to +# the "int_and 512" (lines 48, 147, 154) +# +# - the guards have very long 'liveboxes' lists containing mostly +# Consts -- make sure that these Consts are not stored, or else +# remove them entirely +# +# - dead operation removal: e.g. line 158 + + def run_child(glob, loc): interp = loc['interp'] graph = loc['graph'] From tverwaes at codespeak.net Fri Feb 27 20:34:02 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 27 Feb 2009 20:34:02 +0100 (CET) Subject: [pypy-svn] r62250 - in pypy/trunk/pypy/lang/gameboy: . debug Message-ID: <20090227193402.17772168045@codespeak.net> Author: tverwaes Date: Fri Feb 27 20:34:01 2009 New Revision: 62250 Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py pypy/trunk/pypy/lang/gameboy/video.py Log: some refactorings Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Fri Feb 27 20:34:01 2009 @@ -46,6 +46,8 @@ def print_compare(self, msg, python, java, printall=False): if java != python: self.compare_failed = True + import pdb + pdb.set_trace() print "python: !!", msg, "java:", java, "python:", python, "!!" if printall: print "python: XX", msg, "java:", java, "python:", python, "!!" Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Feb 27 20:34:01 2009 @@ -81,20 +81,22 @@ self.sprites[i] = Sprite(self) def update_all_sprites(self): + # TODO: TEST! for i in range(40): - address = 1 * 4 + address = i * 4 self.sprites[i].set_data(self.oam[address + 0], self.oam[address + 1], self.oam[address + 2], self.oam[address + 3]) def update_sprite(self, address, data): + # TODO: TEST! # XXX why cant I use None here + # (because None == 0 in C?) attribute = [-1] * 4 # assign the data to the correct attribute attribute[address % 4] = data - self.get_sprite(address).set_data(attribute[0], attribute[1], - attribute[2], attribute[3]) + self.get_sprite(address).set_data(*attribute) def get_sprite(self, address): address -= constants.OAM_ADDR @@ -235,7 +237,7 @@ # NOTE: do not reset LY=LYC flag (bit 2) of the STAT register (Mr. Do!) self.line_y = 0 if value != 0: - self.status.set_mode(0x02) + self.status.set_mode(2) self.cycles = constants.MODE_2_TICKS self.display = False else: @@ -468,6 +470,7 @@ self.draw_pixels_line() def draw_sprites_line_new(self): + # XXX Not in use yet. Will replace the hacky version. sprites_on_line = self.get_drawable_sprites_on_line(self.line_y) last_sprite = sprites_on_line[0] @@ -508,8 +511,8 @@ def draw_sprites_line(self): count = self.scan_sprites() - lastx = 176 - for index in range(176, count): + lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE + for index in range(count): data = self.objects[index] x = (data >> 24) & 0xFF flags = (data >> 12) & 0xFF @@ -556,32 +559,29 @@ return count def sort_scan_sprite(self, count): - # sort objects from lower to higher priority + # TODO: optimize :) + # sort objects from high to low priority for index in range(count): - rightmost = index - for number in range(index+1, count): - if (self.objects[number] >> 20) > \ - (self.objects[rightmost] >> 20): - rightmost = number - if rightmost != index: - data = self.objects[index] - self.objects[index] = self.objects[rightmost] - self.objects[rightmost] = data + highest = index + for right in range(index+1, count): + if (self.objects[right] >> 20) > \ + (self.objects[highest] >> 20): + highest = right + self.objects[index], self.objects[rightmost] = self.objects[rightmost], self.objects[index] def draw_tiles(self, x, tile_map, tile_data): while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: - if self.control.background_and_window_lower_tile_data_selected: - tile = self.vram[tile_map] - assert tile == (tile & 0xFF) - else: - tile = (self.vram[tile_map] ^ 0x80) & 0xFF + tile = self.vram[tile_map] + assert tile == (tile & 0xFF) + if not self.control.background_and_window_lower_tile_data_selected: + tile = (tile ^ 0x80) & 0xFF self.draw_tile(x, tile_data + (tile << 4)) tile_map = (tile_map & 0x1FE0) + ((tile_map + 1) & 0x001F) x += SPRITE_SIZE def draw_tile(self, x, address): pattern = self.get_pattern(address) - for i in range(0, 8): + for i in range(0, SPRITE_SIZE): self.line[x + i] = (pattern >> (7-i)) & 0x0101 def get_pattern(self, address): From cami at codespeak.net Fri Feb 27 21:45:44 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 27 Feb 2009 21:45:44 +0100 (CET) Subject: [pypy-svn] r62253 - in pypy/trunk/pypy/lang/gameboy: . debug Message-ID: <20090227204544.D42C9168538@codespeak.net> Author: cami Date: Fri Feb 27 21:45:43 2009 New Revision: 62253 Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_parts.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_mode.py pypy/trunk/pypy/lang/gameboy/video_register.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: changing strange comment some reformatting Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Fri Feb 27 21:45:43 2009 @@ -148,11 +148,9 @@ # LCD Color Palette #COLOR_MAP =[ # 0x9CB916, 0x8CAA14, 0x306430, 0x103F10 - # 0xE0F8D0, 0x88C070, 0x386850, 0x081820 - # 0xFFFFFF, 0xAAAAAA, 0x555555, 0x000000 -# ] - - +# 0xE0F8D0, 0x88C070, 0x386850, 0x081820 +# 0xFFFFFF, 0xAAAAAA, 0x555555, 0x000000 +#] # ___________________________________________________________________________ # JOYPAD @@ -160,12 +158,10 @@ # Joypad Registers P+ JOYP = 0xFF00 - # Joypad Poll Speed (64 Hz) JOYPAD_CLOCK = GAMEBOY_CLOCK >> 6 - BUTTON_DOWN = 0x08 BUTTON_UP = 0x04 BUTTON_LEFT = 0x02 @@ -176,8 +172,6 @@ BUTTON_B = 0x02 BUTTON_A = 0x01 - - # ___________________________________________________________________________ # SERIAL # ___________________________________________________________________________ @@ -192,9 +186,6 @@ SERIAL_TRANSFER_DATA = 0xFF01 SERIAL_TRANSFER_CONTROL = 0xFF02 - - - # ___________________________________________________________________________ # SOUND # ___________________________________________________________________________ @@ -233,12 +224,10 @@ BUFFER_LOG_SIZE = 5; - # ___________________________________________________________________________ # TIMER # ___________________________________________________________________________ - # DIV Timer Speed (16384 Hz) DIV_CLOCK = GAMEBOY_CLOCK >> 14 Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Fri Feb 27 21:45:43 2009 @@ -297,7 +297,7 @@ def store_hl_in_pc(self): # LD PC,HL, 1 cycle self.load(DoubleRegisterCallWrapper(self.hl), - DoubleRegisterCallWrapper(self.pc)) + DoubleRegisterCallWrapper(self.pc)) def fetch_load(self, getCaller, setCaller): self.load(CPUFetchCaller(self), setCaller) @@ -732,7 +732,8 @@ self.cycles += 1 self.fetch() -# ------------------------------------------------------------------------------ +# OP CODE META PROGRAMMING =================================================== +# Call Wrappers -------------------------------------------------------------- class CallWrapper(object): def get(self, use_cycles=True): @@ -790,15 +791,13 @@ # op_code LOOKUP TABLE GENERATION ----------------------------------------------- -GROUPED_REGISTERS = [CPU.get_b, CPU.get_c, CPU.get_d, CPU.get_e, - CPU.get_h, CPU.get_l, CPU.get_hli, CPU.get_a] +GROUPED_REGISTERS = [ CPU.get_b, CPU.get_c, CPU.get_d, CPU.get_e, + CPU.get_h, CPU.get_l, CPU.get_hli, CPU.get_a ] def create_group_op_codes(table): - op_codes =[] + op_codes = [] for entry in table: - op_code = entry[0] - step = entry[1] - function = entry[2] + op_code, step, function = entry[:3] if len(entry) == 4: for registerGetter in GROUPED_REGISTERS: for n in entry[3]: @@ -814,7 +813,7 @@ op_code+=step else: for registerGetter in GROUPED_REGISTERS: - op_codes.append((op_code,group_lambda(function, registerGetter))) + op_codes.append((op_code, group_lambda(function, registerGetter))) op_code += step return op_codes @@ -838,14 +837,12 @@ def load_group_lambda(store_register, load_register): return lambda s: CPU.load(s, RegisterCallWrapper(load_register(s)), - RegisterCallWrapper(store_register(s))) + RegisterCallWrapper(store_register(s))) def create_register_op_codes(table): op_codes = [] for entry in table: - op_code = entry[0] - step = entry[1] - function = entry[2] + op_code, step, function = entry[:3] for registerOrGetter in entry[3]: op_codes.append((op_code, register_lambda(function, registerOrGetter))) op_code += step @@ -856,8 +853,7 @@ return lambda s: function(s, registerOrGetter(s)) else: return lambda s: function(s, registerOrGetter) - - + def initialize_op_code_table(table): result = [None] * (0xFF+1) for entry in table: Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Fri Feb 27 21:45:43 2009 @@ -30,7 +30,7 @@ def __init__(self, debug_connection): self.debug_connection = debug_connection - self.memory_check_skip = 5 + self.memory_check_skip = 1 def compare(self, data): @@ -46,8 +46,6 @@ def print_compare(self, msg, python, java, printall=False): if java != python: self.compare_failed = True - import pdb - pdb.set_trace() print "python: !!", msg, "java:", java, "python:", python, "!!" if printall: print "python: XX", msg, "java:", java, "python:", python, "!!" @@ -281,31 +279,32 @@ ("oam", self.video.oam, "oam"), ("line", self.video.line, "line"), ("objects", self.video.objects, "objects"), - #("palette", self.video.palette, "palette") + ("palette", self.video.palette, "palette") ] self.compare_memory_set(cmp, data, label="video"); @printframe("comparing registers") def compare_registers(self, data): cmp = [ - ("dirty", self.video.dirty, "dirty"), - ("display", self.video.display, "display"), - ("bgp", self.video.background_palette, "bgp"), - ("dma", self.video.dma, "dma"), - ("frames", self.video.frames, "frames"), - ("frameSkip", self.video.frame_skip, "frameSkip"), - ("lcdc", self.video.control.read(), "lcdc"), - ("ly", self.video.line_y, "ly"), - ("obp0", self.video.object_palette_0, "obp0"), - ("obp1", self.video.object_palette_1, "obp1"), - ("scx", self.video.background.scroll_x, "scx"), - ("scy", self.video.background.scroll_y, "scy"), - ("stat", self.video.status.read(), "stat"), - ("transfer", self.video.transfer, "transfer"), - ("vblank", self.video.v_blank, "vblank"), - ("wly", self.video.window.line_y, "wly"), - ("wx", self.video.window.x, "wx"), - ("wy", self.video.window.y, "wy") + ("dirty", self.video.dirty, "dirty"), + ("display", self.video.display, "display"), + ("bgp", self.video.background_palette, "bgp"), + ("dma", self.video.dma, "dma"), + ("frames", self.video.frames, "frames"), + ("frameSkip", self.video.frame_skip, "frameSkip"), + ("lcdc", self.video.control.read(), "lcdc"), + ("ly", self.video.line_y, "ly"), + ("line_y_compare", self.video.line_y_compare, "lyc"), + ("obp0", self.video.object_palette_0, "obp0"), + ("obp1", self.video.object_palette_1, "obp1"), + ("scx", self.video.background.scroll_x, "scx"), + ("scy", self.video.background.scroll_y, "scy"), + ("stat", self.video.status.read(), "stat"), + ("transfer", self.video.transfer, "transfer"), + ("vblank", self.video.v_blank, "vblank"), + ("wly", self.video.window.line_y, "wly"), + ("wx", self.video.window.x, "wx"), + ("wy", self.video.window.y, "wy") ] self.compare_set(cmp, data, label="video") @@ -326,5 +325,7 @@ self.video.emulated_transfer, "emulated_transfer"), ("Check whether emulated VBLank", self.video.emulated_vblank, "emulated_vblank"), + ("Check whether called draw Backgroundw", + self.video.drew_background, "drew_background"), ] self.compare_set(cmp, data, label="video", printall=True) Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py Fri Feb 27 21:45:43 2009 @@ -5,20 +5,24 @@ # ------------------------------------------------------------------------------ -if sys.platform == 'darwin': - from AppKit import NSApplication - NSApplication.sharedApplication() +#if sys.platform == 'darwin': + #from AppKit import NSApplication + #NSApplication.sharedApplication() # ------------------------------------------------------------------------------ ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" filename = ROM_PATH + "/rom9/rom9.gb" SOCKET_PORT = 55682 -skip_count = 6150 -in_between_skip = 1000 -#skip_count = 22545 -#skip_count = 2700 -# skip_count = 0 + +skip_count = 22545 +skip_count = 2700 +skip_count = 0 + +if len(sys.argv) > 1: + skip_count = sys.argv[1] + first_skip = sys.argv[2] + in_between_skips = sys.argv[3] # ------------------------------------------------------------------------------ @@ -31,6 +35,7 @@ def ask_for_skip_count(): global skip_count + if len(sys.argv) > 1: return print ">> enter initial skip amount: ", read = sys.stdin.readline() try: @@ -41,6 +46,7 @@ def ask_for_in_between_skip(): global in_between_skip + if len(sys.argv) > 1: return print ">> enter initial in_between_skip amount: ", read = sys.stdin.readline() try: Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_parts.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_parts.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_parts.py Fri Feb 27 21:45:43 2009 @@ -34,6 +34,7 @@ self.emulated_vblank = False self.emulated_oam = False self.emulated_transfer = False + self.drew_background = False def write(self, address, data): Video.write(self, address, data) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Feb 27 21:45:43 2009 @@ -446,8 +446,6 @@ def current_mode(self): return self.status.current_mode - - # graphics handling -------------------------------------------------------- def draw_frame(self): @@ -465,17 +463,14 @@ if self.window.enabled: self.window.draw_line(self.line_y) if self.control.sprites_enabled: - #self.draw_sprites_line_new() self.draw_sprites_line() self.draw_pixels_line() def draw_sprites_line_new(self): # XXX Not in use yet. Will replace the hacky version. sprites_on_line = self.get_drawable_sprites_on_line(self.line_y) - - last_sprite = sprites_on_line[0] + last_sprite = sprites_on_line[0] last_sprite.draw() - for sprite in sprites_on_line[1:]: if sprite.overlaps_on_line(last_sprite, self.line_y): sprite.draw_overlapped() @@ -486,7 +481,7 @@ found = [] for i in range(len(self.sprites)): if self.sprites[i].intersects_line(line_y) and \ - self.sprites[i].enabled: + self.sprites[i].enabled: found.append(self.sprites[i]) return found @@ -509,6 +504,51 @@ # ----------------------------------------------- + def draw_sprites_line_new(self): + count = self.scan_sprites_new() + lastx = 176 + for index in range(176, count): + paint_sprite = self.objects[index] + x = (data >> 24) & 0xFF + flags = (data >> 12) & 0xFF + address = data & 0xFFF + if (paint_sprite.x + SPRITE_SIZE <= lastx): + self.draw_object_tile_new(paint_sprite) + else: + self.draw_overlapped_object_tile_new(x, address, flags) + lastx = paint_sprite.x + + def scan_sprites_new(self): + count = 0 + # search active objects + for offset in range(0, 4*40, 4): + sprite = self.get_sprite(offset) + if sprite.hide_check(): continue + paint_sprite = PaintSprite(count, sprite, self) + self.objects[count] = paint_sprite + count += 1 + if count >= constants.OBJECTS_PER_LINE: break + self.sort_scan_sprite_new(count) + return count + + def sort_scan_sprite_new(self, count): + # sort objects from higher to lower priority + for index in range(count): + rightmost = index + for number in range(index+1, count): + if (self.objects[number].line_position) > \ + (self.objects[rightmost].line_position): + rightmost = number + if rightmost != index: + self.swap_object_indices(rightmost, index) + + def swap_object_indices(self, index_a, index_b): + data = self.objects[index_a] + self.objects[index_a] = self.objects[index_b] + self.objects[index_b] = data + + # --------------------------------------------------------------------- + def draw_sprites_line(self): count = self.scan_sprites() lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE @@ -522,33 +562,33 @@ else: self.draw_overlapped_object_tile(x, address, flags) lastx = x - + def scan_sprites(self): count = 0 # search active objects for offset in range(0, 4*40, 4): - y = self.oam[offset + 0] - x = self.oam[offset + 1] - if (y <= 0 or y >= SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE - or x <= 0 or x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE): + y = self.get_oam(offset + 0) + x = self.get_oam(offset + 1) + if y <= 0 \ + or y >= (SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE) \ + or x <= 0 \ + or x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE: continue - tile = self.oam[offset + 2] - flags = self.oam[offset + 3] - y = self.line_y - y + 16 + tile = self.get_oam(offset + 2) + flags = self.get_oam(offset + 3) + y = self.line_y - y + 2 * SPRITE_SIZE if self.control.big_sprite_size_selected: # 8x16 tile size - if (y < 0 or y > 15): - continue + if y < 0 or y > 15: continue # Y flip - if ((flags & 0x40) != 0): + if (flags & 0x40) != 0: y = 15 - y tile &= 0xFE else: # 8x8 tile size - if (y < 0 or y > 7): - continue + if y < 0 or y > 7: continue # Y flip - if ((flags & 0x40) != 0): + if (flags & 0x40) != 0: y = 7 - y self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + \ (tile << 4) + (y << 1) Modified: pypy/trunk/pypy/lang/gameboy/video_mode.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_mode.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_mode.py Fri Feb 27 21:45:43 2009 @@ -194,7 +194,6 @@ """ Mode 3: The LCD controller is reading from both OAM and VRAM, The CPU access OAM and VRAM during this period. - CGB Mode: Cannot access Palette Data (FF69,FF6B) either. """ def reset(self): pass Modified: pypy/trunk/pypy/lang/gameboy/video_register.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_register.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_register.py Fri Feb 27 21:45:43 2009 @@ -51,14 +51,14 @@ return value def write(self, value, write_all=False): - if write_all: - self.current_mode = self.modes[value & 0x03] - self.line_y_compare_flag = bool(value & (1 << 2)) - self.status = bool(value & (1 << 7)) self.mode0.h_blank_interrupt = bool(value & (1 << 3)) self.mode1.v_blank_interrupt = bool(value & (1 << 4)) self.mode2.oam_interrupt = bool(value & (1 << 5)) self.line_y_compare_interrupt = bool(value & (1 << 6)) + if write_all: + self.current_mode = self.modes[value & 0x03] + self.line_y_compare_flag = bool(value & (1 << 2)) + self.status = bool(value & (1 << 7)) def get_mode(self): return self.current_mode.id() Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Feb 27 21:45:43 2009 @@ -104,6 +104,7 @@ self.hidden = True else: self.hidden = False + return self.hidden def get_tile_number(self): return self.tile.id @@ -128,6 +129,31 @@ def draw_overlapped(self): pass +# ----------------------------------------------------------------------------- + +class PaintSprite(Sprite): + + def __init__(self, line_position, sprite, video): + Sprite.__init__(self) + self.line_position = line_position + self.extract_attributes(sprite, video) + self.update_position(sprite) + + def extract_attributes(self, sprite, video): + self.x = sprite.x + self.y = video.line_y - sprite.y + 2 * SPRITE_SIZE + self.tile = sprite.tile + self.object_behind_background = sprite.object_behind_background + self.x_flipped = sprite.x_flipped + self.y_flipped = sprite.y_flipped + self.tile_number = sprite.tile_number + self.hidden = sprite.hidden + self.rest_attributes_and_flags = sprite.rest_attributes_and_flags + + def update_position(sprite): + if sprite.y < 0 or sprite.y >= self.get_height(): return + if sprite.y_flipped: + self.y = self.get_height() - 1 - self.y # ----------------------------------------------------------------------------- From cami at codespeak.net Fri Feb 27 22:18:25 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 27 Feb 2009 22:18:25 +0100 (CET) Subject: [pypy-svn] r62254 - pypy/trunk/pypy/lang/gameboy/debug Message-ID: <20090227211825.35FCC168552@codespeak.net> Author: cami Date: Fri Feb 27 22:18:23 2009 New Revision: 62254 Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Log: removed an invalid compare test for video Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Fri Feb 27 22:18:23 2009 @@ -324,8 +324,6 @@ ("Check whether emulated Transfer", self.video.emulated_transfer, "emulated_transfer"), ("Check whether emulated VBLank", - self.video.emulated_vblank, "emulated_vblank"), - ("Check whether called draw Backgroundw", - self.video.drew_background, "drew_background"), + self.video.emulated_vblank, "emulated_vblank") ] self.compare_set(cmp, data, label="video", printall=True) From cami at codespeak.net Fri Feb 27 22:18:51 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 27 Feb 2009 22:18:51 +0100 (CET) Subject: [pypy-svn] r62255 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090227211851.5CC2A168555@codespeak.net> Author: cami Date: Fri Feb 27 22:18:50 2009 New Revision: 62255 Modified: pypy/trunk/pypy/lang/gameboy/cartridge.py pypy/trunk/pypy/lang/gameboy/cpu.py pypy/trunk/pypy/lang/gameboy/gameboy.py pypy/trunk/pypy/lang/gameboy/test/test_memory_bank_controller.py pypy/trunk/pypy/lang/gameboy/video.py Log: removed some superfluous imports of pdb Modified: pypy/trunk/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cartridge.py (original) +++ pypy/trunk/pypy/lang/gameboy/cartridge.py Fri Feb 27 22:18:50 2009 @@ -12,7 +12,6 @@ #from pypy.rlib.rstr import str_replace import os -import pdb # HELPERS ---------------------------------------------------------------------- Modified: pypy/trunk/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/cpu.py (original) +++ pypy/trunk/pypy/lang/gameboy/cpu.py Fri Feb 27 22:18:50 2009 @@ -4,7 +4,6 @@ from pypy.lang.gameboy.interrupt import * from pypy.lang.gameboy.cpu_register import Register, DoubleRegister, \ FlagRegister, ImmediatePseudoRegister -import pdb # --------------------------------------------------------------------------- Modified: pypy/trunk/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy.py Fri Feb 27 22:18:50 2009 @@ -16,7 +16,6 @@ from pypy.lang.gameboy.video import * from pypy.lang.gameboy.cartridge import * -import pdb class GameBoy(object): Modified: pypy/trunk/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_memory_bank_controller.py Fri Feb 27 22:18:50 2009 @@ -3,7 +3,6 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants import py -import pdb class TestClock(object): def __init__(self): @@ -256,7 +255,6 @@ mbc.ram_enable = True for address in range(0xA000, 0xBFFF+1): mbc.write(address, value) - #pdb.runcall(mbc.write, address, value) assert mbc.ram[mbc.ram_bank + (address & 0x1FFF)] == value assert mbc.read(address) == value; value += 1 Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Feb 27 22:18:50 2009 @@ -543,9 +543,9 @@ self.swap_object_indices(rightmost, index) def swap_object_indices(self, index_a, index_b): - data = self.objects[index_a] - self.objects[index_a] = self.objects[index_b] - self.objects[index_b] = data + data = self.objects[index_a] + self.objects[index_a] = self.objects[index_b] + self.objects[index_b] = data # --------------------------------------------------------------------- From tverwaes at codespeak.net Fri Feb 27 23:15:28 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 27 Feb 2009 23:15:28 +0100 (CET) Subject: [pypy-svn] r62257 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090227221528.662E9168561@codespeak.net> Author: tverwaes Date: Fri Feb 27 23:15:26 2009 New Revision: 62257 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_mode.py Log: bugfixes. call to get_oam has to take global memory position into account... maybe should switch to internal versions? Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Feb 27 23:15:26 2009 @@ -567,15 +567,15 @@ count = 0 # search active objects for offset in range(0, 4*40, 4): - y = self.get_oam(offset + 0) - x = self.get_oam(offset + 1) + y = self.get_oam(constants.OAM_ADDR + offset + 0) + x = self.get_oam(constants.OAM_ADDR + offset + 1) if y <= 0 \ or y >= (SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE) \ or x <= 0 \ or x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE: continue - tile = self.get_oam(offset + 2) - flags = self.get_oam(offset + 3) + tile = self.get_oam(constants.OAM_ADDR + offset + 2) + flags = self.get_oam(constants.OAM_ADDR + offset + 3) y = self.line_y - y + 2 * SPRITE_SIZE if self.control.big_sprite_size_selected: # 8x16 tile size @@ -668,7 +668,7 @@ for i in range(0, 7): color = pattern >> (6-i) if (color & 0x0202) != 0: - caller.call(x+1, color, mask) + caller.call(x + i + 1, color, mask) color = pattern << 1 if (color & 0x0202) != 0: caller.call(x+7, color, mask) Modified: pypy/trunk/pypy/lang/gameboy/video_mode.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_mode.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_mode.py Fri Feb 27 23:15:26 2009 @@ -84,11 +84,11 @@ def emulate_hblank_part_2(self): if self.video.display: self.video.draw_frame() - self.video.frames += 1 if self.video.frames >= self.video.frame_skip: self.video.display = True self.video.frames = 0 else: + self.video.frames += 1 self.video.display = False self.video.status.set_mode(1) self.video.v_blank = True From cami at codespeak.net Fri Feb 27 23:23:10 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 27 Feb 2009 23:23:10 +0100 (CET) Subject: [pypy-svn] r62258 - in pypy/trunk/pypy/lang/gameboy: . debug Message-ID: <20090227222310.558FB168549@codespeak.net> Author: cami Date: Fri Feb 27 23:23:09 2009 New Revision: 62258 Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py Log: remove some catches in order to have a usefull traceback Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Fri Feb 27 23:23:09 2009 @@ -278,8 +278,8 @@ ("vram", self.video.vram, "vram"), ("oam", self.video.oam, "oam"), ("line", self.video.line, "line"), - ("objects", self.video.objects, "objects"), - ("palette", self.video.palette, "palette") + ("objects", self.video.objects, "objects") + # ("palette", self.video.palette, "palette") ] self.compare_memory_set(cmp, data, label="video"); Modified: pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/gameboy_debug_entry_point.py Fri Feb 27 23:23:09 2009 @@ -19,10 +19,15 @@ skip_count = 2700 skip_count = 0 +skip_count = 0 +first_skip = 0 +in_between_skip = 0 + + if len(sys.argv) > 1: skip_count = sys.argv[1] first_skip = sys.argv[2] - in_between_skips = sys.argv[3] + in_between_skip = sys.argv[3] # ------------------------------------------------------------------------------ @@ -67,12 +72,13 @@ except Exception, error: gameBoy.load_cartridge_file(str(filename), verify=False) print "Cartridge is Corrupted!" - try: - gameBoy.mainLoop() - except Exception, error: - print "stopped" - print error - pdb.set_trace() + gameBoy.mainLoop() + #try: + # gameBoy.mainLoop() + #except Exception, error: + # print "stopped" + # print error + # pdb.set_trace() # ------------------------------------------------------------------------------ Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Fri Feb 27 23:23:09 2009 @@ -37,12 +37,14 @@ def mainLoop(self): self.reset() self.is_running = True - try: - while self.is_running: - self.emulate_cycle() - except Exception, error: - self.is_running = False - self.handle_execution_error(error) + while self.is_running: + self.emulate_cycle() + #try: + # while self.is_running: + # self.emulate_cycle() + #except Exception, error: + # self.is_running = False + # self.handle_execution_error(error) return 0 def emulate_cycle(self): Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Feb 27 23:23:09 2009 @@ -544,8 +544,7 @@ def swap_object_indices(self, index_a, index_b): data = self.objects[index_a] - self.objects[index_a] = self.objects[index_b] - self.objects[index_b] = data + self.objects[index_a] = sself.objects[index_b] = data # --------------------------------------------------------------------- From tverwaes at codespeak.net Fri Feb 27 23:40:17 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 27 Feb 2009 23:40:17 +0100 (CET) Subject: [pypy-svn] r62259 - in pypy/trunk/pypy/lang/gameboy: . debug Message-ID: <20090227224017.76427168553@codespeak.net> Author: tverwaes Date: Fri Feb 27 23:40:16 2009 New Revision: 62259 Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py pypy/trunk/pypy/lang/gameboy/video.py Log: aargl Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Fri Feb 27 23:40:16 2009 @@ -278,8 +278,8 @@ ("vram", self.video.vram, "vram"), ("oam", self.video.oam, "oam"), ("line", self.video.line, "line"), - ("objects", self.video.objects, "objects") - # ("palette", self.video.palette, "palette") + ("objects", self.video.objects, "objects"), + ("palette", self.video.palette, "palette"), ] self.compare_memory_set(cmp, data, label="video"); Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Feb 27 23:40:16 2009 @@ -542,9 +542,8 @@ if rightmost != index: self.swap_object_indices(rightmost, index) - def swap_object_indices(self, index_a, index_b): - data = self.objects[index_a] - self.objects[index_a] = sself.objects[index_b] = data + def swap_object_indices(self, a, b): + self.objects[a], self.objects[b] = self.objects[b], self.objects[a] # --------------------------------------------------------------------- From cami at codespeak.net Fri Feb 27 23:45:23 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 27 Feb 2009 23:45:23 +0100 (CET) Subject: [pypy-svn] r62260 - in pypy/trunk/pypy/lang/gameboy: . debug Message-ID: <20090227224523.1D22F168561@codespeak.net> Author: cami Date: Fri Feb 27 23:45:22 2009 New Revision: 62260 Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_util.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: fixing wrong variable name in video small reformatting Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_util.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_util.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_util.py Fri Feb 27 23:45:22 2009 @@ -7,7 +7,7 @@ # # ---------------------------------------------------------------------------- -DEBUG = True +DEBUG = False DEBUG_PRINT_LOGS = True op_codes = [0] * (0xFF+1) fetch_execute_op_codes = [0] * (0xFF+1) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Feb 27 23:45:22 2009 @@ -605,7 +605,7 @@ if (self.objects[right] >> 20) > \ (self.objects[highest] >> 20): highest = right - self.objects[index], self.objects[rightmost] = self.objects[rightmost], self.objects[index] + self.objects[index], self.objects[highest] = self.objects[highest], self.objects[index] def draw_tiles(self, x, tile_map, tile_data): while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Feb 27 23:45:22 2009 @@ -256,8 +256,8 @@ self.video.line[x] = 0x00 def draw_line(self, line_y): - y = (self.scroll_y + line_y) & 0xFF - x = self.scroll_x & 0xFF + y = (self.scroll_y + line_y) & 0xFF + x = self.scroll_x & 0xFF tile_map, tile_data = self.prepare_background_data(x, y) self.video.draw_tiles(8 - (x & 7), tile_map, tile_data) From tverwaes at codespeak.net Fri Feb 27 23:47:01 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 27 Feb 2009 23:47:01 +0100 (CET) Subject: [pypy-svn] r62261 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090227224701.5E287168561@codespeak.net> Author: tverwaes Date: Fri Feb 27 23:47:00 2009 New Revision: 62261 Modified: pypy/trunk/pypy/lang/gameboy/video.py Log: nicer code layout :) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Fri Feb 27 23:47:00 2009 @@ -605,7 +605,8 @@ if (self.objects[right] >> 20) > \ (self.objects[highest] >> 20): highest = right - self.objects[index], self.objects[highest] = self.objects[highest], self.objects[index] + self.objects[index], self.objects[highest] = \ + self.objects[highest], self.objects[index] def draw_tiles(self, x, tile_map, tile_data): while x < GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: From cami at codespeak.net Fri Feb 27 23:49:14 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 27 Feb 2009 23:49:14 +0100 (CET) Subject: [pypy-svn] r62262 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090227224914.94A6C16856A@codespeak.net> Author: cami Date: Fri Feb 27 23:49:13 2009 New Revision: 62262 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: inverting Window.draw_line precondition Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Fri Feb 27 23:49:13 2009 @@ -213,10 +213,8 @@ return constants.VRAM_MAP_A def draw_line(self, line_y): - if line_y < self.y or self.x >= 167 or \ - self.line_y >= GAMEBOY_SCREEN_HEIGHT: - return - else: + if line_y >= self.y and self.x < 167 and \ + self.line_y < GAMEBOY_SCREEN_HEIGHT: tile_map, tile_data = self.prepare_window_data() self.video.draw_tiles(self.x + 1, tile_map, tile_data) self.line_y += 1 From cami at codespeak.net Sat Feb 28 00:00:40 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 28 Feb 2009 00:00:40 +0100 (CET) Subject: [pypy-svn] r62263 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090227230040.2E98016856C@codespeak.net> Author: cami Date: Sat Feb 28 00:00:37 2009 New Revision: 62263 Modified: pypy/trunk/pypy/lang/gameboy/video.py Log: fixing draw_pixels_line in video, wrong increment Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 00:00:37 2009 @@ -466,6 +466,8 @@ self.draw_sprites_line() self.draw_pixels_line() + # ----------------------------------------------- + def draw_sprites_line_new(self): # XXX Not in use yet. Will replace the hacky version. sprites_on_line = self.get_drawable_sprites_on_line(self.line_y) @@ -678,8 +680,7 @@ offset = self.line_y * self.driver.get_width() for x in range(SPRITE_SIZE, GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE, 4): for i in range(0,4): - value = self.palette[self.line[x + 1]] - pixels[offset + i] = value + pixels[offset + i] = self.palette[self.line[x + i]] offset += 4 def clear_pixels(self): From tverwaes at codespeak.net Sat Feb 28 00:05:52 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 28 Feb 2009 00:05:52 +0100 (CET) Subject: [pypy-svn] r62265 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090227230552.94B1B16856C@codespeak.net> Author: tverwaes Date: Sat Feb 28 00:05:51 2009 New Revision: 62265 Modified: pypy/trunk/pypy/lang/gameboy/video.py Log: fixed a bug; of course we need to keep the mask on the color Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 00:05:51 2009 @@ -24,7 +24,7 @@ self.video = video def call(self, pos, color, mask): - self.video. set_overlapped_object_line(pos, color, mask) + self.video.set_overlapped_object_line(pos, color, mask) class set_tile_line_call_wrapper(VideoCallWraper): @@ -657,21 +657,21 @@ self.draw_object_normal(x, pattern, mask, caller) def draw_object_flipped(self, x, pattern, mask, caller): - color = pattern << 1 - if (color & 0x0202) != 0: + color = (pattern << 1) & 0x0202 + if color != 0: caller.call(x, color, mask) for i in range(0, 7): - color = pattern >> i - if (color & 0x0202) != 0: + color = (pattern >> i) & 0x0202 + if color != 0: caller.call(x + i + 1, color, mask) def draw_object_normal(self, x, pattern, mask, caller): for i in range(0, 7): - color = pattern >> (6-i) - if (color & 0x0202) != 0: - caller.call(x + i + 1, color, mask) - color = pattern << 1 - if (color & 0x0202) != 0: + color = (pattern >> (6-i)) & 0x0202 + if color != 0: + caller.call(x + i, color, mask) + color = (pattern << 1) & 0x0202 + if color != 0: caller.call(x+7, color, mask) def draw_pixels_line(self): From cami at codespeak.net Sat Feb 28 00:11:33 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 28 Feb 2009 00:11:33 +0100 (CET) Subject: [pypy-svn] r62266 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090227231133.865431684C5@codespeak.net> Author: cami Date: Sat Feb 28 00:11:32 2009 New Revision: 62266 Modified: pypy/trunk/pypy/lang/gameboy/video.py Log: compacting draw_pixels_line and conquerred the array bounds ;) Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 00:11:32 2009 @@ -677,11 +677,9 @@ def draw_pixels_line(self): self.update_palette() pixels = self.driver.get_pixels() - offset = self.line_y * self.driver.get_width() - for x in range(SPRITE_SIZE, GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE, 4): - for i in range(0,4): - pixels[offset + i] = self.palette[self.line[x + i]] - offset += 4 + offset = self.line_y * self.driver.get_width() - SPRITE_SIZE + for x in range(SPRITE_SIZE, GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE): + pixels[offset + x] = self.palette[self.line[x]] def clear_pixels(self): self.driver.clear_pixels() From cami at codespeak.net Sat Feb 28 00:32:53 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 28 Feb 2009 00:32:53 +0100 (CET) Subject: [pypy-svn] r62267 - pypy/trunk/pypy/lang/gameboy/debug Message-ID: <20090227233253.720BB168560@codespeak.net> Author: cami Date: Sat Feb 28 00:32:52 2009 New Revision: 62267 Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Log: set debug to False, less verbose output Modified: pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py (original) +++ pypy/trunk/pypy/lang/gameboy/debug/debug_comparator.py Sat Feb 28 00:32:52 2009 @@ -326,4 +326,4 @@ ("Check whether emulated VBLank", self.video.emulated_vblank, "emulated_vblank") ] - self.compare_set(cmp, data, label="video", printall=True) + self.compare_set(cmp, data, label="video", printall=False) From cami at codespeak.net Sat Feb 28 00:33:13 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 28 Feb 2009 00:33:13 +0100 (CET) Subject: [pypy-svn] r62268 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090227233313.B440A168564@codespeak.net> Author: cami Date: Sat Feb 28 00:33:12 2009 New Revision: 62268 Modified: pypy/trunk/pypy/lang/gameboy/video.py Log: stuff Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 00:33:12 2009 @@ -530,7 +530,7 @@ self.objects[count] = paint_sprite count += 1 if count >= constants.OBJECTS_PER_LINE: break - self.sort_scan_sprite_new(count) + self.sort_scan_sprite_new_sprite_new(count) return count def sort_scan_sprite_new(self, count): From tverwaes at codespeak.net Sat Feb 28 01:37:12 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 28 Feb 2009 01:37:12 +0100 (CET) Subject: [pypy-svn] r62269 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090228003712.B0F6B168549@codespeak.net> Author: tverwaes Date: Sat Feb 28 01:37:10 2009 New Revision: 62269 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/test/test_video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: fixed some nice bug in the sprite. Now the nintendo logo pops up nicely again for selected roms. Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Sat Feb 28 01:37:10 2009 @@ -48,6 +48,8 @@ return 0 def emulate_cycle(self): + print "Emulating!" + self.joypad_driver.button_up(True) self.handle_events() self.emulate(constants.GAMEBOY_CLOCK >> 2) if use_rsdl: Modified: pypy/trunk/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video.py Sat Feb 28 01:37:10 2009 @@ -507,4 +507,4 @@ video.background.draw_clean_line(video.line_y) assert video.line == [0] * (8+160+8) - \ No newline at end of file + Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Sat Feb 28 01:37:10 2009 @@ -20,6 +20,7 @@ self.x_flipped = False self.y_flipped = False self.tile_number = 0 + self.palette_number = 0 self.hidden = True self.rest_attributes_and_flags = 0 @@ -85,15 +86,15 @@ self.object_behind_background = bool(data & (1 << 7)) self.x_flipped = bool(data & (1 << 6)) self.y_flipped = bool(data & (1 << 5)) - self.tile_number = bool(data & (1 << 4)) - self.rest_attributes_and_flags = data & (1+2+4+8) + self.palette_number = bool(data & (1 << 4)) + self.rest_attributes_and_flags = data & (1+2+4+8) def get_attributes_and_flags(self): value = 0 value += int(self.object_behind_background) << 7 value += int(self.x_flipped) << 6 value += int(self.y_flipped) << 5 - value += int(self.tile_number) << 4 + value += int(self.palette_number) << 4 value += self.rest_attributes_and_flags return value From tverwaes at codespeak.net Sat Feb 28 02:10:06 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 28 Feb 2009 02:10:06 +0100 (CET) Subject: [pypy-svn] r62270 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090228011006.DFC4E168547@codespeak.net> Author: tverwaes Date: Sat Feb 28 02:10:05 2009 New Revision: 62270 Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py pypy/trunk/pypy/lang/gameboy/video.py Log: translates with RSDL; the nintendo logo appears and the hello world cartridge works! Modified: pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py (original) +++ pypy/trunk/pypy/lang/gameboy/gameboy_implementation.py Sat Feb 28 02:10:05 2009 @@ -7,7 +7,7 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants -use_rsdl = False +use_rsdl = True if use_rsdl: from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi @@ -48,8 +48,7 @@ return 0 def emulate_cycle(self): - print "Emulating!" - self.joypad_driver.button_up(True) + # self.joypad_driver.button_up(True) self.handle_events() self.emulate(constants.GAMEBOY_CLOCK >> 2) if use_rsdl: Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 02:10:05 2009 @@ -96,7 +96,10 @@ attribute = [-1] * 4 # assign the data to the correct attribute attribute[address % 4] = data - self.get_sprite(address).set_data(*attribute) + self.get_sprite(address).set_data(attribute[0], + attribute[1], + attribute[2], + attribute[3]) def get_sprite(self, address): address -= constants.OAM_ADDR From tverwaes at codespeak.net Sat Feb 28 18:17:02 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 28 Feb 2009 18:17:02 +0100 (CET) Subject: [pypy-svn] r62272 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090228171702.5F6B81684CF@codespeak.net> Author: tverwaes Date: Sat Feb 28 18:17:00 2009 New Revision: 62272 Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: refactorings. fully moving towards sprites and readability Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Sat Feb 28 18:17:00 2009 @@ -10,7 +10,8 @@ GAMEBOY_SCREEN_WIDTH = 160 GAMEBOY_SCREEN_HEIGHT = 144 -SPRITE_SIZE = 8 +SPRITE_SIZE = 8 +SPRITE_BYTES = 4 #___________________________________________________________________________ # CATRIGE TYPES Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 18:17:00 2009 @@ -569,30 +569,29 @@ def scan_sprites(self): count = 0 # search active objects - for offset in range(0, 4*40, 4): - y = self.get_oam(constants.OAM_ADDR + offset + 0) - x = self.get_oam(constants.OAM_ADDR + offset + 1) + for offset in range(0, SPRITE_BYTES * 40, SPRITE_BYTES): + sprite = self.get_sprite(OAM_ADDR + offset) + x = sprite.x + y = sprite.y if y <= 0 \ or y >= (SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE) \ or x <= 0 \ or x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE: continue - tile = self.get_oam(constants.OAM_ADDR + offset + 2) - flags = self.get_oam(constants.OAM_ADDR + offset + 3) - y = self.line_y - y + 2 * SPRITE_SIZE + tile = sprite.tile_number + y = self.line_y - y + 2 * SPRITE_SIZE if self.control.big_sprite_size_selected: # 8x16 tile size - if y < 0 or y > 15: continue - # Y flip - if (flags & 0x40) != 0: - y = 15 - y + tile_size = 15 tile &= 0xFE else: # 8x8 tile size - if y < 0 or y > 7: continue - # Y flip - if (flags & 0x40) != 0: - y = 7 - y + tile_size = 7 + if y < 0 or y > tile_size: continue + # Y flip + if sprite.y_flipped: + y = tile_size - y + # TODO: build an object abstraction? self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + \ (tile << 4) + (y << 1) count += 1 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Sat Feb 28 18:17:00 2009 @@ -29,7 +29,7 @@ def get_data(self): return [self.y, self.x, self.tile_number, self.get_attributes_and_flags()] - + def set_data(self, byte0=-1, byte1=-1, byte2=-1, byte3=-1): """ extracts the sprite data from an oam entry From tverwaes at codespeak.net Sat Feb 28 18:30:11 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 28 Feb 2009 18:30:11 +0100 (CET) Subject: [pypy-svn] r62273 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090228173011.8E733168534@codespeak.net> Author: tverwaes Date: Sat Feb 28 18:30:11 2009 New Revision: 62273 Modified: pypy/trunk/pypy/lang/gameboy/constants.py pypy/trunk/pypy/lang/gameboy/video.py Log: more refactoring Modified: pypy/trunk/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/constants.py (original) +++ pypy/trunk/pypy/lang/gameboy/constants.py Sat Feb 28 18:30:11 2009 @@ -11,7 +11,6 @@ GAMEBOY_SCREEN_HEIGHT = 144 SPRITE_SIZE = 8 -SPRITE_BYTES = 4 #___________________________________________________________________________ # CATRIGE TYPES Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 18:30:11 2009 @@ -526,8 +526,7 @@ def scan_sprites_new(self): count = 0 # search active objects - for offset in range(0, 4*40, 4): - sprite = self.get_sprite(offset) + for sprite in self.sprites: if sprite.hide_check(): continue paint_sprite = PaintSprite(count, sprite, self) self.objects[count] = paint_sprite @@ -569,15 +568,10 @@ def scan_sprites(self): count = 0 # search active objects - for offset in range(0, SPRITE_BYTES * 40, SPRITE_BYTES): - sprite = self.get_sprite(OAM_ADDR + offset) + for sprite in self.sprites: x = sprite.x y = sprite.y - if y <= 0 \ - or y >= (SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE) \ - or x <= 0 \ - or x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE: - continue + if sprite.hidden: continue tile = sprite.tile_number y = self.line_y - y + 2 * SPRITE_SIZE if self.control.big_sprite_size_selected: @@ -588,7 +582,6 @@ # 8x8 tile size tile_size = 7 if y < 0 or y > tile_size: continue - # Y flip if sprite.y_flipped: y = tile_size - y # TODO: build an object abstraction? From cami at codespeak.net Sat Feb 28 18:30:30 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 28 Feb 2009 18:30:30 +0100 (CET) Subject: [pypy-svn] r62274 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090228173030.1715C16853A@codespeak.net> Author: cami Date: Sat Feb 28 18:30:30 2009 New Revision: 62274 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: fixed sprite hidden check Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Sat Feb 28 18:30:30 2009 @@ -99,9 +99,9 @@ return value def hide_check(self): - if self.y <= 0 or self.y >= GAMEBOY_SCREEN_WIDTH: + if self.y <= 0 or self.y >= SPRITE_SIZE + GAMEBOY_SCREEN_HEIGHT + SPRITE_SIZE: self.hidden = True - elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH+SPRITE_SIZE: + elif self.x <= 0 or self.x >= GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE: self.hidden = True else: self.hidden = False From cami at codespeak.net Sat Feb 28 19:32:00 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 28 Feb 2009 19:32:00 +0100 (CET) Subject: [pypy-svn] r62275 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090228183200.387C4168549@codespeak.net> Author: cami Date: Sat Feb 28 19:31:58 2009 New Revision: 62275 Modified: pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: externalized sprite painting, shortened scan_sprites Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 19:31:58 2009 @@ -555,41 +555,23 @@ count = self.scan_sprites() lastx = SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE for index in range(count): - data = self.objects[index] - x = (data >> 24) & 0xFF - flags = (data >> 12) & 0xFF - address = data & 0xFFF + sprite = self.objects[index] + x = sprite.x if (x + SPRITE_SIZE <= lastx): - self.draw_object_tile(x, address, flags) + sprite.draw(self) else: - self.draw_overlapped_object_tile(x, address, flags) + sprite.draw_overlapped(self) lastx = x def scan_sprites(self): - count = 0 # search active objects + count = 0 for sprite in self.sprites: - x = sprite.x - y = sprite.y - if sprite.hidden: continue - tile = sprite.tile_number - y = self.line_y - y + 2 * SPRITE_SIZE - if self.control.big_sprite_size_selected: - # 8x16 tile size - tile_size = 15 - tile &= 0xFE - else: - # 8x8 tile size - tile_size = 7 - if y < 0 or y > tile_size: continue - if sprite.y_flipped: - y = tile_size - y - # TODO: build an object abstraction? - self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + \ - (tile << 4) + (y << 1) - count += 1 - if count >= constants.OBJECTS_PER_LINE: - break + if not sprite.hidden and sprite.visible_on_line(self.line_y): + self.objects[count] = sprite + count += 1 + if count >= constants.OBJECTS_PER_LINE: + break self.sort_scan_sprite(count) return count @@ -599,8 +581,7 @@ for index in range(count): highest = index for right in range(index+1, count): - if (self.objects[right] >> 20) > \ - (self.objects[highest] >> 20): + if self.objects[right].x > self.objects[highest].x: highest = right self.objects[index], self.objects[highest] = \ self.objects[highest], self.objects[index] @@ -624,20 +605,20 @@ return self.vram[address] + (self.vram[address + 1] << 8) - def draw_object_tile(self, x, address, flags): - self.draw_object(set_tile_line_call_wrapper(self), x, address, flags) + def draw_object_tile(self, x, y, address, flags): + self.draw_object(set_tile_line_call_wrapper(self), x, y, address, flags) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask - def draw_overlapped_object_tile(self, x, address, flags): + def draw_overlapped_object_tile(self, x, y, address, flags): self.draw_object(set_overlapped_object_line_call_wrapper(self), - x, address, flags) + x, y, address, flags) def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask - def draw_object(self, caller, x, address, flags): + def draw_object(self, caller, x, y, address, flags): pattern = self.get_pattern(address) mask = 0 # priority Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Sat Feb 28 19:31:58 2009 @@ -107,6 +107,10 @@ self.hidden = False return self.hidden + def visible_on_line(self, line_y): + y = self.get_draw_y() + return y < 0 or y > (self.get_height() -1) + def get_tile_number(self): return self.tile.id @@ -125,11 +129,28 @@ def intersects_line(self, line): return line >= self.y and line <= self.y + self.get_height() - def draw(self): - pass - - def draw_overlapped(self): - pass + def get_draw_y(self, line_y): + return line_y - self.y + 2 * SPRITE_SIZE + + def get_draw_address_data(line_y): + tile = sprite.tile_number + if self.big_size: + tile &= 0xFE + tile_size = self.get_height() -1 + y = self.get_draw_y(line_y) + if sprite.y_flipped: + y = tile_size - y + return (tile << 4) + (y << 1) + + def draw(self, video): + video.draw_object_tile(self.x, self.y, \ + self.get_draw_address_data(video.line_y), \ + self.get_attributes_and_flags()) + + def draw_overlapped(self, video): + video.draw_overlapped_object_tile(self.x, self.y, \ + self.get_draw_address_data(video.line_y), \ + self.get_attributes_and_flags()) # ----------------------------------------------------------------------------- class PaintSprite(Sprite): From cami at codespeak.net Sat Feb 28 19:34:28 2009 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 28 Feb 2009 19:34:28 +0100 (CET) Subject: [pypy-svn] r62276 - pypy/trunk/pypy/lang/gameboy Message-ID: <20090228183428.649FD168549@codespeak.net> Author: cami Date: Sat Feb 28 19:34:27 2009 New Revision: 62276 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: missing argument Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Sat Feb 28 19:34:27 2009 @@ -108,7 +108,7 @@ return self.hidden def visible_on_line(self, line_y): - y = self.get_draw_y() + y = self.get_draw_y(line_y) return y < 0 or y > (self.get_height() -1) def get_tile_number(self): From tverwaes at codespeak.net Sat Feb 28 20:02:17 2009 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 28 Feb 2009 20:02:17 +0100 (CET) Subject: [pypy-svn] r62277 - in pypy/trunk/pypy/lang/gameboy: . test Message-ID: <20090228190217.106FF16855C@codespeak.net> Author: tverwaes Date: Sat Feb 28 20:02:11 2009 New Revision: 62277 Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py pypy/trunk/pypy/lang/gameboy/video.py pypy/trunk/pypy/lang/gameboy/video_sprite.py Log: making it translate again. broken sprite drawing though Modified: pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/test/test_video_sprite.py Sat Feb 28 20:02:11 2009 @@ -57,19 +57,19 @@ def test_video_sprite_read_write(): sprite = get_sprite() for i in range(0xFF): - sprite.set_data(byte0=i) + sprite.set_data_at(0, i) assert sprite.get_data()[0] == i for i in range(0xFF): - sprite.set_data(byte1=i) + sprite.set_data_at(1, i) assert sprite.get_data()[1] == i for i in range(0xFF): - sprite.set_data(byte2=i) + sprite.set_data_at(2, i) assert sprite.get_data()[2] == i for i in range(0xFF): - sprite.set_data(byte3=i) + sprite.set_data_at(3, i) assert sprite.get_data()[3] == i def test_size(): Modified: pypy/trunk/pypy/lang/gameboy/video.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video.py (original) +++ pypy/trunk/pypy/lang/gameboy/video.py Sat Feb 28 20:02:11 2009 @@ -139,7 +139,7 @@ #XXX remove those dumb helper "objects" self.line = [0] * (SPRITE_SIZE + GAMEBOY_SCREEN_WIDTH + SPRITE_SIZE) - self.objects = [0] * constants.OBJECTS_PER_LINE + self.objects = [None] * constants.OBJECTS_PER_LINE self.palette = [0] * 1024 self.frames = 0 Modified: pypy/trunk/pypy/lang/gameboy/video_sprite.py ============================================================================== --- pypy/trunk/pypy/lang/gameboy/video_sprite.py (original) +++ pypy/trunk/pypy/lang/gameboy/video_sprite.py Sat Feb 28 20:02:11 2009 @@ -30,18 +30,25 @@ def get_data(self): return [self.y, self.x, self.tile_number, self.get_attributes_and_flags()] - def set_data(self, byte0=-1, byte1=-1, byte2=-1, byte3=-1): + def set_data_at(self, address, data): + actual = address % 4 + if actual == 0: + self.extract_y_position(data) + if actual == 1: + self.extract_x_position(data) + if actual == 2: + self.extract_tile_number(data) + if actual == 3: + self.extract_attributes_and_flags(data) + + def set_data(self, y_position, x_position, tile_number, attributes_and_flags): """ extracts the sprite data from an oam entry """ - if byte0 is not -1: - self.extract_y_position(byte0) - if byte1 is not -1: - self.extract_x_position(byte1) - if byte2 is not -1: - self.extract_tile_number(byte2) - if byte3 is not -1: - self.extract_attributes_and_flags(byte3) + self.extract_y_position(y_position) + self.extract_x_position(x_position) + self.extract_tile_number(tile_number) + self.extract_attributes_and_flags(attributes_and_flags) def extract_y_position(self, data): """ @@ -132,13 +139,13 @@ def get_draw_y(self, line_y): return line_y - self.y + 2 * SPRITE_SIZE - def get_draw_address_data(line_y): - tile = sprite.tile_number + def get_draw_address_data(self, line_y): + tile = self.tile_number if self.big_size: tile &= 0xFE tile_size = self.get_height() -1 y = self.get_draw_y(line_y) - if sprite.y_flipped: + if self.y_flipped: y = tile_size - y return (tile << 4) + (y << 1)